Ruby - Variables that are defined only once per function call [duplicate] - c++

Is there any such thing as static variables in Ruby that would behave like they do in C functions?
Here's a quick example of what I mean. It prints "6\n7\n" to the console.
#include <stdio.h>
int test() {
static int a = 5;
a++;
return a;
}
int main() {
printf("%d\n", test());
printf("%d\n", test());
return 0;
}

What I understand about this C code is that the static variable is initialized with a value (5 in this case), and its value is persisted across function calls.
In Ruby and languages with the same level of abstraction, this same thing is typically achieved either by using a variable that sits outside the scope of the function or by using an object to hold that variable.
def test()
#a ||= 5 # If not set, set it. We need to use an instance variable to persist the variable across calls.
#a += 1 # sum 1 and return it's value
end
def main()
puts test
puts test
0
end
Ruby's quirk is that you can use instance variables even outside of a class definition.

Similar to nicooga's answer but more self-contained:
def some_method
#var ||= 0
#var += 1
puts #var
end

Scope your variable in a method and return lambda
def counter
count = 0
lambda{count = count+1}
end
test = counter
test[]
#=>1
test[]
#=>2

You can use a global variable:
$a = 5
def test
$a += 1
end
p test #=> 6
p test #=> 7

Use a variable in the singleton class (The static class itself)
class Single
def self.counter
if #count
#count+=1
else
#count = 5
end
end
end
In ruby, any class is an object which has only one instance.
Therefore, you can create an instance variable on the class, and it will work as a "static" method ;)
Output:
ruby 2.5.5p157 (2019-03-15 revision 67260) [x86_64-linux]
=> :counter
Single.counter
=> 5
Single.counter
=> 6
Single.counter
=> 7
To get this behaviour on the main scope, you can do:
module Countable
def counter
if #count
#count+=1
else
#count = 5
end
end
end
=> :counter
self.class.prepend Countable # this "adds" the method to the main object
=> Object
counter
=> 5
counter
=> 6
counter
=> 7

I think a standard way to do this is to use Fiber.
f = Fiber.new do
a = 5
loop{Fiber.yield a += 1}
end
puts f.resume # => 6
puts f.resume # => 7
...

Related

In Raku, doesn't routine first return Nil when no values match?

According to Raku documentation, routine first returns Nil when no values match. However, why doesn't the line say ($result === Nil) ; (below) print True?
sub MAIN()
{
my #myNumberList is Array[Int] = [2, 2, 5, 7] ;
my $result = #myNumberList.first( {$_ > 10} ) ;
say '$result' ;
say $result ;
say $result.WHAT ;
say ($result === Nil) ;
} # end sub MAIN
Program output is …
$result
(Any)
(Any)
False
Update
My goal was to determine whether a list or an array contains one or more elements satisfying a given predicate. In the following sample program, the elems routine returns a value that is greater than 0 if and only if the given list or array contains at least one element satisfying the predicate given in the corresponding call to grep .
sub MAIN()
{
my $myList = (2, 2, 5, 7) ;
say '$myList' ;
say $myList ;
say $myList.WHAT ;
my $grepResult1 = $myList.grep( * > 10, :p ) ;
say '$grepResult1' ;
say $grepResult1 ;
say $grepResult1.WHAT ;
say ($grepResult1.elems <= 0) ;
my $grepResult2 = $myList.grep( * > 4, :p ) ;
say '$grepResult2' ;
say $grepResult2 ;
say $grepResult2.WHAT ;
say ($grepResult2.elems <= 0) ;
my #myArray = [2, 2, 5, 7] ;
say '#myArray' ;
say #myArray ;
say #myArray.WHAT ;
my $grepResult3 = #myArray.grep( * > 10, :p ) ;
say '$grepResult3' ;
say $grepResult3 ;
say $grepResult3.WHAT ;
say ($grepResult3.elems <= 0) ;
} # end sub MAIN
Program output is …
$myList
(2 2 5 7)
(List)
$grepResult1
()
(Seq)
True
$grepResult2
(2 => 5 3 => 7)
(Seq)
False
#myArray
[2 2 5 7]
(Array)
$grepResult3
()
(Seq)
True
Interesting question that appears to be (somewhat) addressed on the "Traps To Avoid" documentation page. See the specific subheading: "Assignment of Nil can produce a different value, usually 'Any' ". Also, the Raku documentation page on class Nil .
The short answer--as near as I can surmise--is to use smartmatching with a Junction on the right-hand-side:
Sample Code:
sub MAIN()
{
my #myNumberList is Array[Int] = [2, 2, 5, 7] ;
my $result = #myNumberList.first( {$_ > 10} ) ;
say '$result' ;
say $result ;
say $result.WHAT ;
"\n".say;
say Nil ~~ all($result); #True
say Nil ~~ any($result); #True
say Nil ~~ one($result); #True
say Nil ~~ none($result); #False
"\n".say;
my $result2 = #myNumberList.first( {$_ < 10} ) ;
say Nil ~~ all($result2); #False
say Nil ~~ any($result2); #False
say Nil ~~ one($result2); #False
say Nil ~~ none($result2); #True
} # end sub MAIN
Returns:
$result
(Any)
(Any)
True
True
True
False
False
False
False
True
Alternatively, you can simplify the above code (and clean up your output) using .defined:
for result above (where there are no matching values) say $result if $result.defined; returns nothing;
for result2 above (where the first matching value is 2) say $result2 if $result2.defined; returns 2.
For further reading to understand how the smartmatch solution(s) posted above came about, look at the following Github issue: "In general, the left side of ~~ should not be auto-threading".
[Also, (at the risk of confusing the reader), take a look at the Raku code posted on the following Perl5 doc page: https://perldoc.perl.org/perlsyn#Differences-from-Raku ].
ADDENDUM: For a discussion on the 'do-something-only-if-defined' idiom in Raku, see Damian Conway's talk "On The Shoulders of Giants", which includes his code for a user-defined ?= ("assign-if-defined") operator.
TL;DR Yes, first returns Nil when no values match. One way to get what you want is to bind the result (with :=) instead of assigning it (with =).
A simple solution
Switch from the assignment operator (=) to the binding operator (:=):
sub MAIN()
{
my #myNumberList is Array[Int] = [2, 2, 5, 7] ;
my $result := #myNumberList.first( {$_ > 10} ) ; # <-- Add colon
say '$result' ;
say $result ;
say $result.WHAT ;
say ($result === Nil) ;
} # end sub MAIN
displays:
$result
Nil
Nil
True
What's happening in your original code
In Raku, doesn't routine first return Nil when no values match?
Yes. That's not the problem.
Nil represents "Absence of a value ...".¹
So don't think of it as a value like, say, 42 or 'string' or an empty list².
Assigning Nil to a variable resets the variable's value to its default:
my $foo is default(42) = Nil;
say $foo; # 42
The default default value for a variable is Any³, so:
my $bar = Nil;
say $bar; # (Any)
That's what happened in your original code.
Options
You could set $result's default to Nil so that when you assign Nil to it you get what you want:
my $result is default (Nil) = #myNumberList.first( {$_ > 10} ) ;
But that's cumbersome. And seldom desirable.
Usually, if you want a variable to keep a Nil, you just bind it instead of assigning it:
my $qux := Nil; # <-- use `:=` instead of `=`
say $qux; # Nil
Just set your mental model to match what Raku's doing and you'll find it's all really simple.⁴
Footnotes
¹ Per its doc, Nil is "Absence of a value or a benign failure". The "Absence of a value" aspect applies if you call first to find the first value in some list of values that matches a predicate, but there were no such values. The "benign failure" applies if you call first and it encounters some error condition and either decides it's benign but ought terminate its processing, or throws an exception that gets handled such that further evaluation continues with the code that receives the value returned by first.
As you read this footnote you might think these two cases would best be handled separately. But if you think further you will hopefully see that they work beautifully as two sides of the same coin. Any called code can return Nil, and calling code knows that the result of the call is an absence of a value. This may be due to entirely normal processing which yields no value, or due to processing that encountered an error, but that error was either considered by the called code as so benign as to not be worth reporting to the caller other than by returning Nil, or resulted in an exception being thrown that was subsequently handled to clear the error condition -- thus returning processing to normal status. Raku's elegant and practical Nil is yet another reason why I ❤ Raku.
² An empty list is a still a value. Albeit an empty one.
³ Any is a type. When treated as a "value" it's a type object representing an undefined value of type Any or a subtype thereof. It makes a natural default default value for variables and parameters.
⁴ I suspect I offended folk by writing my "Just ..." sentence. I thought about deleting or editing it, but then folk wouldn't have context for #jubilatious1's comment and my point, which I think is a good one that #jubilatious1 misunderstood, would be lost. I'm leaving it in with this footnote for now in the hope someone will engage with me if they think it is a problem and/or if it would be a good idea for me to remove it or, conversely, unstrike it.

Is there an alternative to an if statement in Lua?

I would like to know if there is a alternative to using a normal if statement in lua. For example, in java there are switch statements but I cant seem to find that in Lua
Lua lacks a C-style switch statement.
A simple version of a switch statement can be implemented using a table to map the case value to an action. This is very efficient in Lua since tables are hashed by key value which avoids repetitive if then ... elseif ... end statements.
action = {
[1] = function (x) print(1) end,
[2] = function (x) z = 5 end,
["nop"] = function (x) print(math.random()) end,
["my name"] = function (x) print("fred") end,
}
The frequently used pattern
local var; if condition then var = x else var = y end
can be shortened using an and-or "ternary" substitute if x is truthy:
local var = condition and x or y
if test == nil or test == false then return 0xBADEAFFE else return test end
Can be shorten up to...
return test or 0xBADEAFFEE
This works even where you dont can do: if ... then ... else ... end
Like in a function...
print(test or 0xBADEAFFE)
-- Output: 3135156222
...or fallback to a default if an argument is ommited...
function check(test)
local test = test or 0xBADEAFFE
return test
end
print(check())
-- Returns: 3135156222

When I defined a function I got: error unexpected token: (

I have already seen the community of Crystal, but I couldn't find this problem.
def Twosum(a = [] of Int32, target = 0)
map = {} of Int32 : Int32
a.each_index do |i|
diff = target - a[i]
if map.key?(diff):
return [map.fetch(diff), i]
elsif
map[a[i]] = i
end
end
return 0`enter code here`
end
a = [1,4,6,3]
target = 7
puts(Twosum(a,target))
What's the problem?
Many problems. The one you ask about is: Crystal is very opinionated regarding case. Methods must start with lowercase; yours starts with uppercase, which Crystal does not like at all. Some other problems:
{} of Int32 : Int32 should use a fat arrow, not a colon: {} of Int32 => Int32
if statement does not end with a colon, it is not Python.
There is no method named key?; use has_key?
fetch (in current Crystal version) requires either a block or a second argument that specifies a default; if you do not need to specify a default behaviour (and you don't, since you check whether the key exists), you can just use [].
I'm really not sure what the code is intended to do, so I can't comment on the logic, semantics and style; but here's your code without syntax errors:
def twosum(a = [] of Int32, target = 0)
map = {} of Int32 => Int32
a.each_index do |i|
diff = target - a[i]
if map.has_key?(diff)
return [map[diff], i]
elsif
map[a[i]] = i
end
end
return 0
end
a = [1, 4, 6, 3]
target = 7
puts(twosum(a, target))

Are there alternatives to begin/end with stricter scope?

In Crystal, are there any alternatives to the following, but without creating the value of b after the end?
my_val = begin
a = 1
b = 2
a + b
end
b should be undefined here.
I release it's possible to use -> {}.call (but this creates an unneeded closure). There's also 1.times { ... }, but this seems hacky. Is there a shortcut to this within the language itself that is idiomatic?
For your particular case the following could be not idiomatic, but depending on what you want to achieve this can be good to be aware of:
Macro
myval = {% begin %}
a = 1
b = 2
a + b
{% end %}
myval #=> 3
b #=> undefined local variable or method 'b' (did you mean 'p'?)
Method
def myval
a = 1
b = 2
a + b
end
myval #=> 3
b #=> undefined local variable or method 'b' (did you mean 'p'?)
Block
myval = :any.try do
a = 1
b = 2
a + b
end
myval #=> 3
b #=> undefined local variable or method 'b' (did you mean 'p'?)

Scala spec unit tests

I ve got the following class and I want to write some Spec test cases, but I am really new to it and I don't know how to start. My class do loke like this:
class Board{
val array = Array.fill(7)(Array.fill(6)(None:Option[Coin]))
def move(x:Int, coin:Coin) {
val y = array(x).indexOf(None)
require(y >= 0)
array(x)(y) = Some(coin)
}
def apply(x: Int, y: Int):Option[Coin] =
if (0 <= x && x < 7 && 0 <= y && y < 6) array(x)(y)
else None
def winner: Option[Coin] = winner(Cross).orElse(winner(Naught))
private def winner(coin:Coin):Option[Coin] = {
val rows = (0 until 6).map(y => (0 until 7).map( x => apply(x,y)))
val cols = (0 until 7).map(x => (0 until 6).map( y => apply(x,y)))
val dia1 = (0 until 4).map(x => (0 until 6).map( y => apply(x+y,y)))
val dia2 = (3 until 7).map(x => (0 until 6).map( y => apply(x-y,y)))
val slice = List.fill(4)(Some(coin))
if((rows ++ cols ++ dia1 ++ dia2).exists(_.containsSlice(slice)))
Some(coin)
else None
}
override def toString = {
val string = new StringBuilder
for(y <- 5 to 0 by -1; x <- 0 to 6){
string.append(apply(x, y).getOrElse("_"))
if (x == 6) string.append ("\n")
else string.append("|")
}
string.append("0 1 2 3 4 5 6\n").toString
}
}
Thank you!
I can only second Daniel's suggestion, because you'll end up with a more practical API by using TDD.
I also think that your application could be nicely tested with a mix of specs2 and ScalaCheck. Here the draft of a Specification to get you started:
import org.specs2._
import org.scalacheck.{Arbitrary, Gen}
class TestSpec extends Specification with ScalaCheck { def is =
"moving a coin in a column moves the coin to the nearest empty slot" ! e1^
"a coin wins if" ^
"a row contains 4 consecutive coins" ! e2^
"a column contains 4 consecutive coins" ! e3^
"a diagonal contains 4 consecutive coins" ! e4^
end
def e1 = check { (b: Board, x: Int, c: Coin) =>
try { b.move(x, c) } catch { case e => () }
// either there was a coin before somewhere in that column
// or there is now after the move
(0 until 6).exists(y => b(x, y).isDefined)
}
def e2 = pending
def e3 = pending
def e4 = pending
/**
* Random data for Coins, x position and Board
*/
implicit def arbitraryCoin: Arbitrary[Coin] = Arbitrary { Gen.oneOf(Cross, Naught) }
implicit def arbitraryXPosition: Arbitrary[Int] = Arbitrary { Gen.choose(0, 6) }
implicit def arbitraryBoardMove: Arbitrary[(Int, Coin)] = Arbitrary {
for {
coin <- arbitraryCoin.arbitrary
x <- arbitraryXPosition.arbitrary
} yield (x, coin)
}
implicit def arbitraryBoard: Arbitrary[Board] = Arbitrary {
for {
moves <- Gen.listOf1(arbitraryBoardMove.arbitrary)
} yield {
val board = new Board
moves.foreach { case (x, coin) =>
try { board.move(x, coin) } catch { case e => () }}
board
}
}
}
object Cross extends Coin {
override def toString = "x"
}
object Naught extends Coin {
override def toString = "o"
}
sealed trait Coin
The e1 property I've implemented is not the real thing because it doesn't really check that we moved the coin to the nearest empty slot, which is what your code and your API suggests. You will also want to change the generated data so that the Boards are generated with an alternation of x and o. That should be a great way to learn how to use ScalaCheck!
I suggest you throw all that code out -- well, save it somewhere, but start from zero using TDD.
The Specs2 site has plenty examples of how to write tests, but use TDD -- test driven design -- to do it. Adding tests after the fact is suboptimal, to say the least.
So, think of the most simple case you want to handle of the most simple feature, write a test for that, see it fail, write the code to fix it. Refactor if necessary, and repeat for the next most simple case.
If you want help with how to do TDD in general, I heartily endorse the videos about TDD available on Clean Coders. At the very least, watch the second part where Bob Martin writes a whole class TDD-style, from design to end.
If you know how to do testing in general but are confused about Scala or Specs, please be much more specific about what your questions are.