I recently installed J and was playing in jconsole. Here's what then end of my session looked like:
quit
|value error: quit
exit
2!:55
I searched the web and quickly found that the correct exit code is
exit''
Since meaningless words give value errors, and no substring of "exit" is valid J, why is a value given for "exit"? What does 2!:55 mean?
2!:55 is the definition of exit. When you enter a verb without arguments, J shows you its definition. eg:
f =: *:
f 5
25
f
*:
Same with every other predefined verb:
echo
0 0&$#(1!:2&2)
every
&>
each
&.>
etc.
Related
I am learning Julia, and in particular I am trying to get a grasp of macros, so I found, amongst other things Some useful macros for Julia - Github, and in the process of deciphering them I got this behavior in the REPL :
julia> macro once_then(expr::Expr)
#assert expr.head == :while
esc(quote
$(expr.args[2]) # body of loop
$expr # loop
end)
end
#once_then (macro with 1 method)
julia> i = 0
0
julia> #once_then while i < 10
i += 1
end
ERROR: UndefVarError: i not defined
Stacktrace:
[1] macro expansion at ./REPL[34]:2 [inlined]
[2] top-level scope at ./REPL[31]:5
julia> i
1
It clearly had access to i in the first iteration of the loop, since it incremented it, but then did i become Undefed somewhere between the end of the first loop and the beginning of the second ?
From what I can see the parenthesis after esc should include everything up to the end of the loop...
I literally just copy-pasted the code into the terminal, and I get the same behavior from the #until macro found at Julia language - Until loop, so I don't think the problem would come from the code itself... is there something crucial I'm missing ?
(btw, I'm running 1.0.4, so it shouldn't be an issue of backwards compatibility...)
Your macro is fine. the problem is the scope of the variables involved. (for more information, look at this: JuliaLang - Scope of Variables
in a nutshell, the variable i in i = 0 is in a global scope, where the loop is in a local scope. in the REPL, you can add the keywork global this to make your code work:
julia> #once_then while i < 10
global i += 1
end
other option is to do all this in a function, so all variables have local scope:
function fn()
i = 0
#once_then while i < 10
i += 1
end
return i
end
This is a follow-up to my previous question.
I am finally able to reproduce the error here:
my #recentList = prompt("Get recentList: e.g. 1 2 3: ").words || (2,4,6);
say "the list is: ", #recentList;
for #recentList -> $x {
say "one element is: ", $x;
say "element type is: ", $x.WHAT;
say "test (1,2,3).tail(\"2\") : ", (1,2,3).tail("2");
say ( (10.rand.Int xx 10) xx 15 ).map: { #($_.tail($x)); };
}
And the results are ok as long as I use the default list by just hitting return at the prompt and not entering anything. But if I enter a number, it gives this error:
Get recentList: e.g. 1 2 3: 2
the list is: [2]
one element is: 2
element type is: (Str)
test (1,2,3).tail("2") : (2 3)
This type cannot unbox to a native integer: P6opaque, Str
in block at intType.p6 line 9
in block <unit> at intType.p6 line 5
If tail("2") works, why does tail($x) fail? Also, in my original code, tail($x.Int) wouldn't correct the problem, but it did here.
This is at best a nanswer. It is a thus-far failed attempt to figure out this problem. I may have just wandered off into the weeds. But I'll publish what I have. If nothing else, maybe it can serve as a reminder that the first three steps below are sensible ones; thereafter I'm gambling on my ability to work my way forward by spelunking source code when I would probably make much faster and more reliable progress by directly debugging the compiler as discussed in the third step.
OK, the first step was an MRE. What you've provided was an E that was fully R and sufficiently M. :)
Step #2 was increasing the M (golfing). I got it down to:
Any.tail('0'); # OK
Any.tail('1'); # BOOM
Note that it can be actual values:
1.tail('1'); # BOOM
(1..2).tail('1'); # BOOM
But some values work:
(1,2).tail('1'); # OK
Step #3 probably should be to follow the instructions in Playing with the code of Rakudo Perl 6 to track the compiler's execution, eg by sticking says in its source code and recompiling it.
You may also want to try out App::MoarVM::Debug. (I haven't.)
Using these approaches you'll have the power to track with absolute precision what the compiler does for any code you throw at it. I recommend you do this even though I didn't. Maybe you can figure out where I've gone wrong.
In the following I trace this problem by just directly spelunking the Rakudo compiler's source code.
A search for "method tail" in the Rakudo sources yielded 4 matches. For my golf the matching method is a match in core/AnyIterableMethods.pm6.
The tail parameter $n clearly isn't a Callable so the pertinent line that continues our spelunking is Rakudo::Iterator.LastNValues(self.iterator,$n,'tail').
A search for this leads to this method in core/Iterator.pm6.
This in turn calls this .new routine.
These three lines:
nqp::if(
n <= 0, # must be HLL comparison
Rakudo::Iterator.Empty, # negative is just nothing
explain why '0' works. The <= operator coerces its operands to numeric before doing the numeric comparison. So '0' coerces to 0, the condition is True, the result is Rakudo::Iterator.Empty, and the Any.tail('0') yields () and doesn't complain.
The code that immediately follows the above three lines is the else branch of the nqp::if. It closes with nqp::create(self)!SET-SELF(iterator,n,f).
That in turn calls the !SET-SELF routine, which has the line:
($!lastn := nqp::setelems(nqp::list, $!size = size)),
Which attempts to assign size, which in our BOOM case is '1', to $!size. But $!size is declared as:
has int $!size;
Bingo.
Or is it? I don't know if I really have correctly tracked the problem down. I'm only spelunking the code in the github repo, not actually running an instrumented version of the compiler and tracing its execution, as discussed as the sensible step #3 for trying to figure out the problem you've encountered.
Worse, when I'm running a compiler it's an old one whereas the code I'm spelunking is the master...
Why does this work?
(*,*).tail('1') # OK
The code path for this will presumably be this method. The parameter $n isn't a Callable so the code path will run thru the path that uses the $n in the lines:
nqp::unless(
nqp::istype($n,Whatever) || $n == Inf,
$iterator.skip-at-least(nqp::elems($!reified) - $n.Int)
The $n == Inf shouldn't be a problem. The == will coerce its operands to numerics and that should take care of $n being '1'.
The nqp::elems($!reified) - $n.Int shouldn't be a problem either.
The nqp ops doc shows that nqp::elems always returns an int. So this boils down to an int - Int which should work.
Hmm.
A blame of these lines shows that the .Int in the last line was only added 3 months ago.
So, clutching at straws, what happens if one tries:
(my int $foo = 1) - '1' # OK
Nope, that's not the problem.
It seems the trail has grown cold or rather I've wandered off the actual execution path.
I'll publish what I've got. Maybe someone else can pick it up from here or I'll have another go in a day or three...
Is there a way to introspect a variable to directly find out what subset it was declared with? Here I create a subset, but introspection points me to its base type:
> subset Prime of Int where .is-prime
(Prime)
> my Prime $x = 23
23
> $x.WHICH
Int|23
I know it has to store the information somewhere, because if I try to reassign a value that doesn't match the subset, it fails:
> $x = 24
Type check failed in assignment to $x; expected Prime but got Int (24)
in block <unit> at <unknown file> line 1
I tried searching through the code, but I quickly get down into files like container.c and perl6_ops.c where the C code makes my eyes glaze over. I thought that X::TypeCheck::Assignment might help (see core/Exception.pm), but it's not clear to me where the expected value comes from. (see also this commit)
I feel like I'm missing something obvious.
I can check that something matches a subset, but that doesn't tell me if it were declared with a particular subset:
> my Int $y = 43;
43
> $y ~~ Prime;
True
I'm using Rakudo Star 2017.01
Inspired by a Zoffix's use of subsets in a recent post.
The value that you stored in $x is an Int. It is acceptable to the container (which you typed to Prime) because Prime is a subtype of Int.
So what you're interested in, is not the value in the container, but the type of the container. To get at the container, Perl 6 has the .VAR method. And that has an .of method to get at the type:
$ 6 'subset Prime of Int where .is-prime; my Prime $x; dd $x.VAR.of'
Prime
I am trying to learn Haskell but it is a little hard as non of my bindings are remembered from the command line; output from my terminal below.
> let b = []
> b
[]
> 1:b
[1]
> b
[]
I have no idea why this is like this can anyone please help.
What did you expect your example to do? From what you've presented, I don't see anything surprising.
Of course, that answer is probably surprising to you, or you wouldn't have asked. And I'll be honest: I can guess what you were expecting. If I'm right, you thought the output would be:
> let b = []
> b
[]
> 1:b
[1]
> b
[1]
Am I right? Supposing I am, then the question is: why isn't it?
Well, the short version is "that's not what (:) does". Instead, (:) creates a new list out of its arguments; x:xs is a new list whose first element is x and the rest of which is identical to xs. But it creates a new list. It's just like how + creates a new number that's the sum of its arguments: is the behavior
> let b = 0
> b
0
> 1+b
1
> b
0
surprising, too? (Hopefully not!)
Of course, this opens up the next question of "well, how do I update b, then?". And this is where Haskell shows its true colors: you don't. In Haskell, once a variable is bound to a value, that value will never change; it's as though all variables and all data types are const (in C-like languages or the latest Javascript standard) or val (in Scala).
This feature of Haskell – it's called being purely functional – is possibly the single biggest difference between Haskell and every single mainstream language out there. You have to think about writing programs in a very different way when you aren't working with mutable state everywhere.
For example, to go a bit further afield, it's quite possible the next thing you'll try will be something like this:
> let b = []
> b
[]
> let b = 1 : b
In that case, what do you think is going to be printed out when you type b?
Well, remember, variables don't change! So the answer is:
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,…
forever – or until you hit control-C and abort.
This is because let b = 1 : b defines a new variable named b; you might as well have written let c = 1 : c. Thus, you're saying "b is a list which is 1 followed by b"; since we know what b is, we can substitute and get "b is a list which is 1 followed by 1 followed by b", and so on forever. Or: b = 1 : b, so substituting in for b we get b = 1 : 1 : b, and substituting in we get b = 1 : 1 : 1 : 1 : ….
(The fact that Haskell produces an infinite list, rather than going into an infinite loop, is because Haskell is non-strict, more popularly referred to as lazy – this is also possibly the single biggest difference between Haskell and every single mainstream language out there. For further information, search for "lazy evaluation" on Google or Stack Overflow.)
So, in the end, I hope you can see why I wasn't surprised: Haskell can't possibly update variable bindings. So since your definition was let b = [], then of course the final result was still [] :-)
Usually, I will use the :: primitive thus:
SomeVariable"_ :: ] DefaultValue
I'm looking for a way to wrap that ugly SOB. I'm trying to reason it. Normally, it would be with a tacit definition. This, for example:
default =: 13 : 'x"_ :: ] y'
fails miserably. Because, of course, in this context:
SomeVariable default DefaultValue
if SomeVariable doesn't exist, J will throw a valence error.
So, how can you wrap ::?
You can indeed wrap :: but if you want to give it a verb argument, you need to deal with the syntactic issues.
For example, you can use an adverb:
fault=:1 :0
u"_ :: ]
)
Or you could convert the verb you are manipulating into a gerund and pass that in (but that would be ugly, so I do not think you want that).
I use,
ORdef_z_ =: ".#[^:(_1< 4!:0#<#[)
'asd' ORdef 3 NB. asd not assigned, returns right.
3
asd =. 'asd' ORdef 3
asd=.'asd' ORdef 22 NB. will return 3 due to previous assignment
asd
3