Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a custom while block

Tags:

ruby

I know that in ruby we can use a while loop, but I want to know if I can create a custom one so I can make something like this:

custom_while i < 5 do
    puts i
    i += 1
end

I currently have this code:

def custom_while(condition)
    loop do
        break if not condition
        yield
    end
end

i = 0
custom_while i < 5 do
    puts i
    i += 1
end

However, when condition is evaluated, it always get true (because it considers the first evaluation of i < 5 = true only.

Any help will be appreciated!

Note: This is for educational purposes only.

like image 289
Giovanni Benussi Avatar asked Sep 22 '16 15:09

Giovanni Benussi


People also ask

Can you make custom Minecraft blocks?

This means that anyone can make a custom block with their own custom geometry and textures WITHOUT turning on the Holiday Creator Features experimental toggle in settings, and custom geometry and textures for blocks are now fair game on the Marketplace!

How do you create a custom block in Matlab?

In the Simulink® Editor, in the Simulation tab, select New > Library. From the User-Defined Functions library, drag a Level-2 MATLAB S-Function block into your new library. Save your library with the filename saturation_lib . Double-click the block to open its Function Block Parameters dialog box.

How do I edit a custom block?

To edit the custom block, you need to click on the three lines on the left of the block as displayed on the screenshot and click save after you change all the modifications that you want to do.


2 Answers

You almost had it. So, your problem is that the condition is only evaluated once? Well, what construct do we know that we can evaluate as often as we want? That's right: functions! So, let's make condition a function (or a Proc in Ruby lingo):

def custom_while(condition)
  loop do
    break unless condition.()
    yield
  end
end

i = 0
custom_while -> { i < 5 } do
  puts i
  i += 1
end
# 0
# 1
# 2
# 3
# 4

This is unfortunately not as nice looking as in other languages. Ruby's syntax and semantics are aggressively optimized for methods that take exactly 1 "function" as an argument. Ruby has a special syntactically and semantically light-weight construct for that, namely blocks. As soon as you have more than one, though, you're out of luck.

Compare this with languages that have proper block literals, like Smalltalk, for example. In Smalltalk, you could write a method while:do:, and call it like this:

i := 0.
while: [i < 5] do: [Transcript write: i. i := i + 1].

In fact, in Smalltalk, the syntax for blocks is so lightweight that there are no control structures at all in the language. if/then/else is simply an instance method of Boolean, for example:

i % 2 == 0 ifTrue: [Transcript write: "even"] ifFalse: [Transcript write: "odd"].

And while is actually an instance method of Block, so in reality, your example would look like this:

i := 0.
[i < 5] whileTrue: [Transcript write: i. i := i + 1]

Note: I make no guarantees for the Smalltalk code, I didn't test it.

like image 163
Jörg W Mittag Avatar answered Oct 20 '22 02:10

Jörg W Mittag


The problem is, the condition is being evaluated before it's passed in, so it will never change.

Make the condition a function that you evaluate inside the loop, or use a macro to make it cleaner.

like image 44
Carcigenicate Avatar answered Oct 20 '22 02:10

Carcigenicate