I have the following parse issue. In the first sample text below, the parse will hit the two command blocks as it finds the parts in the text.
Give the below a try (Rebol 2).
sample-text: {deferred member}
remove-anchors: func [sample-text][
parse sample-text[
some [
to {<a href="javascript:gotoURL('displayContent.aspx?contentID=9}
begin:
thru {);">}
ending:
(print "Command 1 executed" )
to "<"
begin:
thru ">"
ending:
(print "Command 2 executed" )
]
]
return sample-text
]
Result:
remove-anchors sample-text
Command 1 executed
Command 2 executed
However, if I insert the change/part portion of the command, which is expected to remove the text it finds, the first change/part executes but it appears the second portion of the parse command stops as the second execution block doesn't trigger.
sample-text: {deferred member}
remove-anchors: func [sample-text][
parse sample-text[
some [
to {<a href="javascript:gotoURL('displayContent.aspx?contentID=9}
begin:
thru {);">}
ending:
(print "Command 1 executed" change/part begin "" ending) ;<<----- change
to "<"
begin:
thru ">"
ending:
(print "Command 2 executed" change/part begin "" ending) ;<<----- change
]
]
return sample-text
]
Result:
remove-anchors sample-text
Command 1 executed
== "deferred member</a>"
Note the second command didn't seem to execute both by the Print not executing and the parse not completing.
Since I have multiple different types of links in the texts I'm trying to remove these pieces of HTML from, and multiple occurrences in the same text, I figured PARSE was the right solution.
Can anyone see what I am doing wrong?
Your function should work if you use this
remove-anchors: func [sample-text][
parse sample-text[
some [
to {<a href="javascript:gotoURL('displayContent.aspx?contentID=9}
begin:
thru {);">}
ending:
(print "Command 1 executed" change/part begin "" ending)
:begin ; note this
to "<"
begin:
thru ">"
ending:
(print "Command 2 executed" change/part begin "" ending)
]
]
return sample-text
]
Explanation:
The internal parse pointer is at an internal numeric index of 95 after {);">}. After the change command the index is still at 95, but the sample-text is now much shorter and your parse pointer after your second search text "to "<", probably already after the end. You can see that if you use this line
(print "Command 1 executed" change/part begin "" ending print ending) ;<<----- change
in your function, giving you following error
** Script Error: Out of range or past end
** Where: remove-anchors
** Near: print ending
So you have to set back your parse index / pointer to the beginning of the point, where you changed/deleted your text. This you get with :begin after your alteration.
Best advice is to set back / initialize your internal parse pointer anew, if you modified your parse input: After deletion you should go back to the start of your deletion and after insertion / modification you should go first to the start and then to the end of the new item.
Related
I know how to print a variable and a text but I want to make it in the same line, If i Use:
print "text" MYVARIABLE
I got an exception
Expected command
So the question is: there is a way to print text and variable on the same line?
Thank you
Yes! The word primitive is what you are after- see the dictionary definition here.
In brief, you can follow the syntax:
print word "Count turtles: " count turtles
Or
print ( word "There are " count turtles " turtles right now" )
I've been making a 2009 script builder for a few hours now, and I can't figure out how to make it print errors. If I do print(loadstring("a")) it prints into the roblox output nil [string "s"]:1: '=' expected near '<eof>', which == nil. What I want to get is the error it reports at the end : '=' expected near '<eof>', type type is nil, so I have no idea how to get it. If anyone could help that would be greatly appreciated!
Refer to the Lua 5.1 manual, which will point you to the documentation for load:
If there [are] errors, ... returns nil plus the error message.
It's typical for Lua to return error messages as a second return value:
local f, err = loadstring(mycode)
if not f then
print("There was an error: `" .. err .. "`")
end
This err begins with where the error happened, which unhelpfully quotes the input to loadstring.
For example, for the input code "hello there", the error is
[string "hello there"]:1: '=' expected near 'there'
Lua appears to cut the quote off at the first newline or 63 character, whichever is less:
For "hello\there" the error is
[string "hello..."]:2: '=' expected near 'there'
For "helloooooooooooooooooooooooooooooooooooooooooooooooooooooo there" the error is
[string "helloooooooooooooooooooooooooooooooooooooooooooooooooooooo ther..."]:1: '=' expected near 'there'
If you're sure there's no "]: in the first 63 characters/first line of your script, you can just search for that sequence to find where it stops:
local location, message = err:match('^(%[string ".*"%]:%d+:%s+)(.*)$')
This won't be right if your code is, for example, "hello\"]:1: there", which you may want to address.
The simplest way to address it would be to take user control away from the first line that is quoted: prepend the code with your own first line that is nice (and make sure to adjust the line number of the error if you display it to the user:)
local f, err = loadstring("--code\n" .. mycode)
print(err)
Now the error message should always begin
[string "--code..."]:
8th uses namespaces instead of vocabularies. Each namespace has its own integer representation.
ok> ns:a . cr ns:n . cr
4
2
So, 2 is for the number namespace, and 4 is for arrays.
I want to construct an array holding the namespaces which I can then place at the TOS (top of stack).
However, if I just write this
ok> [ ns:a , ns:n ]
Exception: invalid JSON array: at line 1 char 3 in ....: cr (G:;;; +000004c2)
Exception: can't find: :a: at line 1 char 6 in (null): cr (G:??? +00000029)
Exception: can't find: ,: at line 1 char 8 in (null): cr (G:??? +00000029)
Exception: can't find: ]: at line 1 char 15 in (null): n (G:??? +00000029)
I'm the developer of 8th. The solution with ' ns:a is not really what you want, since that puts the word in the array instead of the value that word would return.
You can accomplish what you're looking for by using the backtick:
[ ` ns:a ` ]
The backtick feeds the text up to the next backtick to eval and puts the value (whatever it is) in the JSON you're creating (it's not limited to JSON, it's a general construct).
You can store the function address instead in the array
[ ' ns:n , ' ns:a ]
and access the values by grabbing an array value and exec it
0 a:# w:exec . cr
2
ok>
You can also use anonymous functions
[ ( ns:a ) , ( ns:m ) ]
i try to iterate over a an array which contains weather data. That works fine already and I also can load the datas from the array which are important for me. Therefore I wrote a helping word which looks like this:
: get-value ( hsh str -- str ) swap at* drop ;
[ "main" get-value "temp" get-value ] each 9 [ + ] times
This code pushes the temperature values from the array on the stack and builds the sum. "main" and "temp" are the key values of the arrays.
I execute it with this command: get-weather-list generates the array
"Vienna" get-weather-list [ "main" get-value "temp" get-value ] each 9 [ + ] times
The result is a number on the stack. Now I want to split this call into one or two words. For example:
: get-weather-information ( city -- str )
get-weather-list
[ "main" get-value "temp" get-value ] each 9 [ + ] times ;
The problem is that I don't really understand the word's signature. I always get "The input quotation to “each” doesn't match its expected effect". I tried a lot but can't find a solution to fix this problem. May anyone have an idea? I am grateful for any help :)
Cheers
Stefan
This is a very old question by now, but it still may be useful to someone.
First, about each: the stack effect of the quotation is (... x -- ...).
That means it consumes an input, and outputs nothing. Your quotation worked on the interpreter because it lets you get away with "wrong" code. But for calling each from a defined word, your quotation can't output anything.
So each is not what you want. If you try to push a variable amount of values to the stack, you'll have the same kind of trouble again. Sequence words all output a fixed amount of values.
What you want to do is one of two things:
Make a new sequence with just the values you want, and then call sum on it.
Use something like reduce, to accumulate the sum as you process your list.
For example, with reduce:
get-weather-list 0 [ "main" get-value "temp" get-value + ] reduce ;
I need help turning off this feature if possible from the interactive mode or I'm going to go mad. The REPL insists on an equal sign before every expression if you want the value. I find this very irritating and unintuitive. To make matters worse, if you mistakenly forget the equal sign, it takes you to this secondary prompt which can only be exited by
typing an expression that'll cause an error.
*** str="This is some string"
*** str
>>
>>
>> =
>>
>> =str
stdin:6: unexpected symbol near '='
*** =str
This is some string
*** #str
stdin:1: unexpected symbol near '#'
*** =#str
19
***
*** 545+8
stdin:1: unexpected symbol near '545'
*** =545+8
553
***
I need a lesson in using the REPL:
Is there a way to get rid of the equal sign so that it behaves like other REPLs?
How do you exit from the secondary prompt without doing what I did?
Everything you enter in standalone Lua is treated as a statement, as opposed to an expression. The statements are evaluated, and their results, if any, are printed to the terminal. This is why you need to prepend = (really shorthand for return) to the expressions you gave as example to get them to display properly without error.
The "secondary prompt" you are seeing is what happens when you enter an incomplete statement.
In interactive mode, if you write an incomplete statement, the interpreter waits for its completion by issuing a different prompt.
You exit from it by completing the statement.
However, it's not too difficult to make your own REPL that does what you want. Of course, you lose the ability to progressively build statements from incomplete chunks this way, but maybe you don't need that.
local function print_results(...)
-- This function takes care of nils at the end of results and such.
if select('#', ...) > 1 then
print(select(2, ...))
end
end
repeat -- REPL
io.write'> '
io.stdout:flush()
local s = io.read()
if s == 'exit' then break end
local f, err = load(s, 'stdin')
if err then -- Maybe it's an expression.
-- This is a bad hack, but it might work well enough.
f = load('return (' .. s .. ')', 'stdin')
end
if f then
print_results(pcall(f))
else
print(err)
end
until false
Since Lua 5.3, you don't need the =, because Lua first tries to interpret it as an expression now.
From the reference manual:
In interactive mode, Lua repeatedly prompts and waits for a line. After reading a line, Lua first try to interpret the line as an expression. If it succeeds, it prints its value. Otherwise, it interprets the line as a statement. If you write an incomplete statement, the interpreter waits for its completion by issuing a different prompt.
A little test:
Lua 5.3.0 Copyright (C) 1994-2014 Lua.org, PUC-Rio
> str = 'hello' .. ' Lua'
> str
hello Lua
> 1 + 2
3
>