? MAKE "num RANDOM 1
? IF [:num = 1] [print "Number is one.] [print "Number is zero.]
[:num = 1] is neither FALSE nor TRUE!
Why won't this work? I'm using Imagine LOGO.
It's been a long time since I used LOGO but I seem to recall that the condition didn't have square brackets around it.
You should try something like:
IFELSE :num = 1 [print [Number is 1]] [print [Number is 0]]
ifelse is probably required for the one-or-the-other variant and I think you may need (although this may depend on your dialect) even more square brackets for a sentence with spaces :-)
Related
Let's say I have some rebol / red code. If I load the source text, I get a block, but how can get back the source text from block ? I tried form block but it doesn't give back the source text.
text: {
Red [Title: "Red Pretty Printer"]
out: none ; output text
spaced: off ; add extra bracket spacing
indent: "" ; holds indentation tabs
emit-line: func [] [append out newline]
emit-space: func [pos] [
append out either newline = last out [indent] [
pick [#" " ""] found? any [
spaced
not any [find "[(" last out find ")]" first pos]
]
]
]
emit: func [from to] [emit-space from append out copy/part from to]
clean-script: func [
"Returns new script text with standard spacing."
script "Original Script text"
/spacey "Optional spaces near brackets and parens"
/local str new
] [
spaced: found? spacey
clear indent
out: append clear copy script newline
parse script blk-rule: [
some [
str:
newline (emit-line) |
#";" [thru newline | to end] new: (emit str new) |
[#"[" | #"("] (emit str 1 append indent tab) blk-rule |
[#"]" | #")"] (remove indent emit str 1) break |
skip (set [value new] load/next str emit str new) :new
]
]
remove out ; remove first char
]
print clean-script read %clean-script.r
}
block: load text
LOAD is a higher-level operation with complex behaviors, e.g. it can take a FILE!, a STRING!, or a BLOCK!. Because it does a lot of different things, it's hard to speak of its exact complement as an operation. (For instance, there is SAVE which might appear to be the "inverse" of when you LOAD from a FILE!)
But your example is specifically dealing with a STRING!:
If I load the source text, I get a block, but how can get back the source text from block ?
As a general point, and very relevant matter: you can't "get back" source text.
In your example above, your source text contained comments, and after LOAD they will be gone. Also, a very limited amount of whitespace information is preserved, in the form of the NEW-LINE flag that each value carries. Yet what specific indentation style you used--or whether you used tabs or spaces--is not preserved.
On a more subtle note, small amounts of notational distinction are lost. STRING! literals which are loaded will lose knowledge of whether you wrote them "with quotes" or {with curly braces}...neither Rebol nor Red preserve that bit. (And even if they did, that wouldn't answer the question of what to do after mutations, or with new strings.) There are variations of DATE! input formats, and it doesn't remember which specific one you used. Etc.
But when it comes to talking about code round-tripping as text, the formatting is minor compared to what happens with binding. Consider that you can build structures like:
>> o1: make object! [a: 1]
>> o2: make object! [a: 2]
>> o3: make object! [a: 3]
>> b: compose [(in o1 'a) (in o2 'a) (in o3 'a)]
== [a a a]
>> reduce b
[1 2 3]
>> mold b
"[a a a]"
You cannot simply serialize b to a string as "[a a a]" and have enough information to get equivalent source. Red obscures the impacts of this a bit more than in Rebol--since even operations like to block! on STRING! and system/lexer/transcode appear to do binding into the user context. But it's a problem you will face on anything but the most trivial examples.
There are some binary formats for Rebol2 and Red that attempt to address this. For instance in "RedBin" a WORD! saves its context (and index into that context). But then you have to think about how much of your loaded environment you want dragged into the file to preserve context. So it's certainly opening a can of worms.
This isn't to say that the ability to MOLD things out isn't helpful. But there's no free lunch...so Rebol and Red programs wind up having to think about serialization as much as anyone else. If you're thinking of doing processing on any source code--for the reasons of comment preservation if nothing else--then PARSE should probably be the first thing you reach for.
How can I pass a function as an argument in red?
Or would I not need that in red?
Using does I can define a function "with no arguments or local variables"
f: does [print 1] do f
>> 1
How can I make this work with (multiple) args? does is no the way, what is?
I want something like: (the following does NOT work):
; does NOT work
f: does-with-args [x][print x] do f 23
>> 1
In the last paragraph of this article http://blog.revolucent.net/2009/05/javascript-rebol.html the author says "allow functions to be passed as arguments" so I got excited, but it's also just using does :). But I learned it's possible.
How can I pass a function as an argument in red?
It doesn't seem this is the essence of your question, but you can pass a function as an argument in a couple of ways:
my-func: func [their-func [any-function!]][their-func "Stuff"]
my-func :print
my-func func [thing][probe uppercase thing]
How can I make this work with (multiple) args?
There are two possibilities here. One is APPLY:
my-func: func [thing][print uppercase thing]
apply :my-func ["Foo"]
Another is to build up a block and DO it:
do collect [keep 'my-func keep "Bar"]
do collect [keep :my-func keep "Baz"] ; keeps the function itself
NB: APPLY can be quirky and I don't think is in Red as yet, worth experimenting.
I have the following block of data:
client: ["id" "1234" "name" "foobar" "custom_ip" none]
Strangely, comparing to "none" never seems to work.
if none = (select client "custom_ip") [print "YAY!"]
Though when I print select client "custom_ip" it returns "none".
Why is this? What can I do to determine that that value is none?
There is a difference between a literal value of type NONE! and a WORD! with the spelling NONE.
One can (rightfully, IMO) call it a bug that the console does not differentiate these when giving you the output of an expression:
>> none ;-- a word! that will be looked up to get its value
== none ;-- that value, and it's *not* actually a word!
To get a less deceptive response from the console of the value that the none word evaluated to in that case, we can use mold/all
>> print mold/all none
== #[none]
Or you can just show the type of the result instead of the result itself:
>> type? none
== none!
Although that's deceptive in a sense for similar reasons, as it looks like the word NONE! when it's actually a datatype...
>> type? type? none
== datatype!
Anyway, what you actually got in your example was the word none, hence:
>> if 'none = (select client "custom_ip") [print "OH..."]
OH...
Deceiving console output aside, it's doing a predictable thing. There is actually a shorthand for #[none] currently in Rebol3 for literal nones of a #:
>> client: ["id" "1234" "name" "foobar" "custom_ip" #]
>> if none = (select client "custom_ip") [print "HMM..."]
HMM...
But construction syntax is in flux in general; so it's hard to say what the ultimate answer will be.
Mostly just be aware of the distinction between the word NONE and a value of type NONE!, despite the basic console's dodgy output. (I'll mention that Ren Garden, for instance, uses MOLD/ALL)
For the description, look at #HostileFork's answer, here's just some code I would use in such case:
unless get select client "custom_ip" [print "YAY!"]
See the GET function to evaluate NONE word!.
I have SQL views such as the below:
SELECT e.employeeid as [EmployeeID], e.employeedescnoid as [Employee Name],
mgr.employeedesc as [Works For], vh.[path] as Hierarchy,
vh.HierarchyLevel1 as [Hierarchy Level 1],
vh.HierarchyLevel2 as [Hierarchy Level 2],
vh.HierarchyLevel3 as [Hierarchy Level 3],
They get much bigger and I am having to replace spaces inside the [] brackets with an underscore. Many examples I find either dont work or also replace spaces outside the brackets - is there a regex code I can use in notepadd++ find and replace to do this.
Here is a way to do the job in multiple steps:
Find what: (?<=\[)(\w+) <-- note the space at the end
Replace with: $1_
Make sure that Regular expression is checked.
Click on Replace All as many time as necessary to replace all the spaces.
Another way to do it in multiple steps. Set the Find what to (\[[^ \[\]]*) ([^\[\]]*\]) and the replace with to be \1_\2. On each step one space between the brackets will be replaced.
The regular expression is decoded as follows:
( Start of first capture group
\[ A real square bracket
[^ \[\]]* Zero or more characters that are not space or square brackets
) End of the first capture
One real space
( Start of second capture group
[^\[\]]* Zero or more characters that are not square brackets
\] A real closing bracket
)
If the text within the square brackets must not contain line breaks you could change the Find what to (\[[^ \[\]\r\n]*) ([^\[\]\r\n]*\])
Let's say I have
o: context [
f: func[message /refine message2][
print [message]
if refine [print message 2]
]
]
I can call it like this
do get in o 'f "hello"
But how can I do for the refinement ? something like this that would work
>> do get in o 'f/refine "hello" "world"
** Script Error: in expected word argument of type: any-word
** Near: do get in o 'f/refine
>>
I don't know if there's a way to directly tell the interpreter to use a refinement in invoking a function value. That would require some parameterization of do when its argument is a function! Nothing like that seems to exist...but maybe it's hidden somewhere else.
The only way I know to use a refinement is with a path. To make it clear, I'll first use a temporary word:
>> fword: get in o 'f
>> do compose [(to-path [fword refine]) "hello" "world"]
hello
world
What that second statement evaluates to after the compose is:
do [fword/refine "hello" "world"]
You can actually put function values into paths too. It gets rid of the need for the intermediary:
>> do compose [(to-path compose [(get in o 'f) refine]) "hello" "world"]
hello
world
P.S. you have an extra space between message and 2 above, where it should just be message2
Do this:
o/('f)/refine "hello" "world"
Parens in a path expression are evaluated if they correspond to object field or series pick/poke index references. That makes the above code equivalent to this:
apply get in o 'f ["hello" true "world"]
Note that apply arguments are positional, so you need to know the order the arguments were declared in. You can't do that trick with the function refinements themselves, so you have to use apply or create path expressions to evaluate if you want to parameterize the refinements of the function call.
Use the simple path o/f/refine