Skip to content

Instantly share code, notes, and snippets.

@samuelgoto
Last active November 29, 2017 22:24
Show Gist options
  • Save samuelgoto/84b6f34be7e64a83cf0dd3282d3a4d1a to your computer and use it in GitHub Desktop.
Save samuelgoto/84b6f34be7e64a83cf0dd3282d3a4d1a to your computer and use it in GitHub Desktop.

Heavily inspired by kotlin and groovy, what would the following syntax simplication enable?

a {}

// syntact sugar for

a(function() {});

?

@samuelgoto
Copy link
Author

Here is how ruby deals with these challenges:

def foreach(list)
  puts "Running foreach on #{list}"
  # you can call the block using the yield keyword  
  for i in list
    puts yield(i)
  end
  puts "End of method"
end  

puts ""
puts ""
puts "Sample #1: basic usage of blocks"
puts ""
puts ""

foreach (0..2) {
  # This is how you declare arguments to the block
  |value|
  puts "Hi from the block with args: #{value}"
  'A return value!'
}

puts ""
puts ""
puts "Sample #2: breaks inside blocks"
puts ""
puts ""

# breaks just return from the block and return null.
result = foreach (2..3) {
  puts "Hi from block with break!"
  break
}

puts "Result is nil, right? #{result == nil}."


puts ""
puts ""
puts "Sample #3: breaks inside blocks with for-loops nested"
puts ""
puts ""

# For example, break inside a lambda doesn't leave the
# outer lambda:
for i in 0..2
  puts "Iterating: #{i}!"
  foreach (0..i) {
    |value|
    puts "Iterating #{value}"
    
    # This only leaves the inner foreach, not the outer for
    break
  }
end

puts ""
puts ""
puts "Sample #4: what does continue do?"
puts ""
puts ""

# For example, break inside a lambda doesn't leave the
# outer lambda:
for i in 0..2
  puts "Iterating: #{i}!"
  foreach (0..i) {
    |value|
    puts "Iterating #{value}"
    # This only leaves the inner foreach, not the outer for
    next
  }
end


puts ""
puts ""
puts "Sample #5: what does return do?"
puts ""
puts ""
def foo
  foreach (0..0) {
    return "hello world"
  }
  return "not this"
end

# Returns "hello world" rather than "not this".
foo()

And console:

ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-linux]
   


Sample #1: basic usage of blocks


Running foreach on 0..2
Hi from the block with args: 0
A return value!
Hi from the block with args: 1
A return value!
Hi from the block with args: 2
A return value!
End of method


Sample #2: breaks inside blocks


Running foreach on 2..3
Hi from block with break!
Result is nil, right? true.


Sample #3: breaks inside blocks with for-loops nested


Iterating: 0!
Running foreach on 0..0
Iterating 0
Iterating: 1!
Running foreach on 0..1
Iterating 0
Iterating: 2!
Running foreach on 0..2
Iterating 0


Sample #4: what does continue do?


Iterating: 0!
Running foreach on 0..0
Iterating 0

End of method
Iterating: 1!
Running foreach on 0..1
Iterating 0

Iterating 1

End of method
Iterating: 2!
Running foreach on 0..2
Iterating 0

Iterating 1

Iterating 2

End of method


Sample #5: what does return do?


Running foreach on 0..0
=> "hello world"
   

@samuelgoto
Copy link
Author

Another example in Ruby:

def iffy(condition) 
  if (condition) then
    yield()
  end
end 

iffy (true) {
  puts "This gets executed!"
}
iffy (false) {
  puts "This does not"
}
for i in 0..1 
  puts "Running: #{i}"
  iffy (i == 0) {
    # This does not break from the outer loop!
    # Prints
    #
    # Running: 0 
    # Running: 1
    break
  }
end


for i in 0..1 
  iffy (i == 0) {
    # This does not continue from the outer loop!
    # Prints
    #
    # Running: 0 
    # Running: 1
    next
  }
  puts "Running: #{i}"
end

def foo() 
  iffy (false) {
    return "never executed"
  }
  iffy (true) {
    return "executed!"
  }
  return "blargh, never got here!"
end

# Prints "executed!"
foo()

@samuelgoto
Copy link
Author

samuelgoto commented Oct 30, 2017

Kotlin disallows break and continue inside blocks:

fun unless(condition: Boolean, block: () -> Unit) {
  if (condition) {
    block()
  }
}

fun main(args: Array<String>) {
  println("Hello, world!")
  while (true) {
    unless(true) {
      println("hello")
      // Error:(11, 12) 'break' or 'continue' jumps 
      // across a function or a class boundary
      // break

      // 'return' is not allowed here
      // return
    }
  }
}

@samuelgoto
Copy link
Author

fun case(condition: Boolean, block: () -> Unit) {
    println("This gets called!")
    block()
}

fun select(condition: Boolean, block: () -> Unit) {
  block()
}

fun main(args: Array<String>) {
  var expr: Boolean = true;
    
  select (expr) {
    case (true) {
        println("Totally true")
    }
    case (true) {
        println("Totally false")
    }
  }
}

@samuelgoto
Copy link
Author

samuelgoto commented Nov 29, 2017

Interesting use case in constructors for Ruby:

https://mixandgo.com/blog/mastering-ruby-blocks-in-less-than-5-minutes

let car = new Car() {
  ::color = 1;
  ::size = "large";
}

Could that lead to something like abstract classes?

sort([2, 3, 1, 4], new Comparator() {
  ::compare do (a, b) {
    return a < b;
  }
})

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment