Projects

Ticket #712 (closed enhancement: fixed)

Opened 21 months ago

Last modified 17 months ago

Feature Request: Add Support for C-Level Blocks

Reported by: cwdinfo@… Owned by: lsansonetti@…
Priority: blocker Milestone: MacRuby 0.7
Component: MacRuby Keywords: block
Cc: mike@…

Description

The following (proposed) syntax should work:

open_panel = NSOpenPanel.openPanel
open_panel.beginSheetModalForWindow(@main_window,
    completionHandler:lambda{|arg| 
      puts "Hello, open file and user arg is #{arg}"
      }
    )

Also, this should work:

def handler(arg)
  puts "Hello, open file and user arg is #{arg}" 
end

open_panel = NSOpenPanel.openPanel
open_panel.beginSheetModalForWindow(@main_window,
    completionHandler:handler)

There may be a more elegant Rubyish way to do this, but I'm not seeing how the proper selector syntax would be created. Here's what I mean:

open_panel = NSOpenPanel.openPanel
  open_panel.beginSheetModalForWindow(@main_window) do |arg|
    puts "Hello, open file and user arg is #{arg}"
  end

But the last example gives no hint that the block selector should be completionHandler:

Change History

follow-up: ↓ 2   Changed 21 months ago by martinlagardette@…

I would say the 2nd and 3rd form wouldn't be good to implement.

The 3rd one because, well, some parts are missing (the completionHandler: part). The second one because this looks more like a callback, rather than a Proc/lambda, and would have unexpected behavior from a ruby point of view. In fact, Ruby-wise, it would be expected that "handler" is called and its result is passed to completion handler.

Otherwise, I agree 100% for the first form :-). I wanted to do it when implementing the Proc as callback functions, but we had no C-block supports at the time. I hope we can bring them to life (since a C-block is not that far from a ruby-block, at least in principle).

in reply to: ↑ 1 ; follow-up: ↓ 8   Changed 21 months ago by cwdinfo@…

Replying to martinlagardette@…:

I would say the 2nd and 3rd form wouldn't be good to implement. The 3rd one because, well, some parts are missing (the completionHandler: part). The second one because this looks more like a callback, rather than a Proc/lambda, and would have unexpected behavior from a ruby point of view. In fact, Ruby-wise, it would be expected that "handler" is called and its result is passed to completion handler. Otherwise, I agree 100% for the first form :-). I wanted to do it when implementing the Proc as callback functions, but we had no C-block supports at the time. I hope we can bring them to life (since a C-block is not that far from a ruby-block, at least in principle).

I understand that the 2nd form appears more like a callback, but the expectation of a functional programming language -- which Ruby debatably is -- is that a Proc is a first-class citizen. Therefore, a method should be usable where a Proc or a lambda is. Regarding the third, how about syntax like:

open_panel.beginSheetModalForWindow(@main_window, completionHandler:MACRUBY_BLOCK) do |arg|
  puts "Hello, open file and user arg is #{arg}"
end

The benefit is that you don't wind up shoehorning all your code inside the parentheses of a method call. Dangling close parens are syntax errors waiting to happen.

  Changed 21 months ago by martinlagardette@…

For the 2nd form, that's not really how ruby works. If lambdas and Procs exist, it is for a reason. One of these reasons being that a method is not an object. It's not a first-class citizen. Procs are. What you can do, however, is call method(:handler) to get a Method object. Whatever you do, in ruby, handler will call the handler method and use its result as the object being referenced.

As for the 3rd form, I like it, but we'll have to see how (and if) it is possible to implement it :-).

  Changed 21 months ago by jazzbox@…

my suggestion is:

open_panel = NSOpenPanel.openPanel
  open_panel.beginSheetModalForWindowOnCompletion(@main_window) do |arg|
    puts "Hello, open file and user arg is #{arg}"
  end

follow-up: ↓ 6   Changed 21 months ago by lsansonetti@…

I think only the 1st form should be implemented at the first time. Passing the block inline (3rd form) might be a good idea but I'm afraid of inconsistencies (since the argument name is no longer passed). Also, it wouldn't work if the method accepts 2 blocks.

2nd solution cannot be implemented easily and I think it's not what users would expect (they would expect the method to be called and its return value to be passed, not the method itself).

in reply to: ↑ 5   Changed 21 months ago by demallien@…

As a MacRuby user (and not a dev, for the moment), I definitely prefer that the MacRuby syntax sticks as closely as possible to the Objective-C Cocoa APIs. From my point of view, it's best to leave the rubyfication of the APIs to HotCocoa.

  Changed 20 months ago by mike@…

  • cc mike@… added

Cc Me!

in reply to: ↑ 2   Changed 17 months ago by dev@…

I think this would read well:

open_panel.beginSheetModalForWindow @main_window, completionHandler: do |arg|
  puts "Hello, open file and user arg is #{arg}"
end

It's currently invalid syntax. I haven't thought much about the possible conflicts or technical viability.

Along with it, it would be great if we could define methods taking blocks and they could be called on the ObjC side with C blocks:

def beginSheetModalForWindow(aWindow, completionHandler: &block)
  # …
end

  Changed 17 months ago by lsansonetti@…

  • status changed from new to closed
  • resolution set to fixed

I didn't see this bug. It is a duplicate of #760 which has been implemented. The syntax is easy, you pass a Proc object, like an API that accepts a function pointer.

Note: See TracTickets for help on using tickets.