In the interpreter:
>> qurl: "1234"
== "1234"
>> R: make object! [probe qurl qq: qurl probe qq]
"1234"
"1234"
== make object! [
qq: "1234"
]
This behaves like I'd expect. All "variables" or "words" are global by default.
Using a script:
REBOL []
qurl: "1234"
Q: make object! [
probe join "[Q before qq] qurl: " qurl
qq: qurl
probe join "[Q] qq: " qq
qurl: qurl
probe join "[Q after qurl] qurl: " qurl
]
probe join "[main before Q] qurl: " qurl
Q
probe join "[main after Q] qurl: " qurl
returns:
"[Q before qq] qurl: none"
"[Q] qq: none"
"[Q after qurl] qurl: none"
"[main before Q] qurl: 1234"
"[main after Q] qurl: 1234"
I'd expect that all probe inside the Q object! would return "1234", but none does it.
Why is that?
When Rebol creates an object, it collects the (set-)words from the spec first and uses them to create the new object. The words of the new object are initially assigned to none. The spec is then bound to the new object and evaluated.
In your first example, you haven't included qurl: in your spec, thus is not part of your object. Instead you get the 'global' qurl. In your second example, qurl is part of your object and is initiated with none.
Your options to access the value associated with the 'global' qurl in your second example are:
1. Compose the block so that when the block is evaluated, it accesses the value directly:
Q: make object! compose [
qq: (qurl)
qurl: (qurl)
]
2. Access the word from a 'global' context:
Q: make object! [
qq: system/words/qurl ; Rebol 2
qq: system/contexts/user/qurl ; Rebol 3
]
Related
I have a following programming language grammar:
data Expr = ...
data Stmt = SExpr Expr | SBlock Block | SLet Fundef | ...
data Block = Block [Stmt]
data Fundef = Fundef String [String] Block
data TopDef = TopFun Fundef
With following example syntax:
function long_function_name () = {
let g() = {
{
h()
};
3
}
}
I am trying to use HughesPJ pretty library to create a pretty printer for this language. My attempts so far look like:
instance Pretty Stmt where
pPrint = \case
SExpr e -> pPrint e
SBlock b -> pPrint b
SLet f -> text "let" <+> pPrint f
instance Pretty Block where
pPrint (Block stmts) = lbrace $+$
nest 2 (vcat (punctuate semi (map pPrint stmts))) $+$
rbrace
instance Pretty Fundef where
pPrint (Fundef name args body) = pPrint name <> parens (...) <+> text "=" <+> pPrint body
instance Prettty TopDef where
pPrint (TopFun f) = text "function" <+> pPrint f
The problem is, I want to have { in the same line as the function declaration, but it always makes the indentation of the following lines relative to the column of the bracket instead of being absolute. Should be visible in the pretty print of the example above;
function long_function_name () = {
let g() = {
{
h()
};
3
}
}
Why does it happen and how should I tackle this problem? I would like to avoid as much code duplication as possible.
You’re writing <+> before the body, so the $+$ vertical concatenation is entirely within that horizontal concatenation of the function line, hence it’s all indented. I believe the way to do what you want with pretty is to explicitly match on the block, since it’s part of the vertical layout, i.e.:
pPrint (Fundef name args (Block stmts)) = vcat
[ pPrint name <> parens (...) <+> text "=" <+> lbrace
, nest 2 (vcat (punctuate semi (map pPrint stmts)))
, rbrace
]
The more modern pretty-printing libraries like prettyprinter make this a little easier: nest (or indent, or hang) handles the indentation of lines following the first line in a vertical layout, so you can put the nest around the opening brace and body, and the closing brace outside the nesting, like so:
"prefix" <+> vcat
[ nest 4 $ vcat
[ "{"
, "body"
]
, "}"
]
⇓
prefix {
body
}
(NB. you can use OverloadedStrings like this instead of wrapping literals in text.)
But that won’t work with pretty, which seems to be designed to align the heck out of everything.
I also recommend prettyprinter for its other advantages, for example, a group function that allows you to express “put this on one line if it fits”, which is extremely helpful for making formatting robust & responsive to different rendering contexts.
I am just starting to use gnu-smalltalk. I have taken following code from here to define a class:
Number subclass: Complex [
| realpart imagpart |
"This is a quick way to define class-side methods."
Complex class >> new [
<category: 'instance creation'>
^self error: 'use real:imaginary:'
]
Complex class >> new: ignore [
<category: 'instance creation'>
^self new
]
Complex class >> real: r imaginary: i [
<category: 'instance creation'>
^(super new) setReal: r setImag: i
]
setReal: r setImag: i [ "What is this method with 2 names?"
<category: 'basic'>
realpart := r.
imagpart := i.
^self
]
]
However, I am not able to create any instances of this class. I have tried various methods and following gives least error!
cn := Complex new: real:15 imaginary:25
cn printNl
The error is:
complexNumber.st:24: expected object
Mostly the error is as follows, e.g. if there is no colon after new keyword:
$ gst complexNumber.st
Object: Complex error: use real:imaginary:
Error(Exception)>>signal (ExcHandling.st:254)
Error(Exception)>>signal: (ExcHandling.st:264)
Complex class(Object)>>error: (SysExcept.st:1456)
Complex class>>new (complexNumber.st:7)
UndefinedObject>>executeStatements (complexNumber.st:25)
nil
Also, I am not clear what is this method with 2 names, each with one argument:
setReal: r setImag: i [ "How can there be 2 names and arguments for one method/function?"
<category: 'basic'>
realpart := r.
imagpart := i.
^self
]
I believe usual method should be with one name and argument(s), as from code here :
spend: amount [
<category: 'moving money'>
balance := balance - amount
]
To create the Complex number 25 + 25i evaluate
Complex real: 25 imaginary: 25
How do I know? Because the first part of your question reads
Complex class >> real: r imaginary: i [
<category: 'instance creation'>
^(super new) setReal: r setImag: i
]
Your mistake was to write Complex new: real: 25 imaginary: 25, which doesn't conform to the Smalltalk syntax.
The Smalltalk syntax for a message with, say, 2 (or more) arguments consists of 2 (or more) keywords, ending with colon, followed, each of them, by the corresponding argument.
For example, the method setReal: r setImag: i has two keywords, namely setReal: and setImag: and receives two arguments r and i. The name of the method, which in Smalltalk is called its selector is the Symbol that results from concatenating the keywords, in this case setReal:setImag:.
I am struggling to figure out an issue with manipulating JSON with Aeson lenses. My task is as simple as to add a key to a nested object in JSON. I was able to change the existing keyby means of:
> :set -XOverloadedStrings
> import Control.Lens
> import Data.Aeson
> import Data.Aeson.Lens
> "{ \"a\": { \"b\": 10 } }" & key "a" . key "b" .~ String "jee"
"{\"a\":{\"b\":\"jee\"}}"
But when I try to make it deal with the new key, it just silently fails to add it:
> "{ \"a\": { \"b\": 10 } }" & key "a" . key "c" .~ String "jee"
"{\"a\":{\"b\":10}}"
Certainly it's me doing something wrong, but I figure I'm out of mana to understand what exactly.
Would you kindly point me in the right direction?
Thank you!
As dfeuer noted, at can insert into maps, while key and ix merely traverse elements if they exist. We can do the following:
> "{ \"a\": { \"b\": 10 } }" & key "a" . _Object . at "c" ?~ String "foo"
"{\"a\":{\"b\":10,\"c\":\"foo\"}}
at is a lens focusing on Maybe element-s, and we can insert by setting to Just some element, and remove by setting to Nothing. at "c" ?~ String "foo" is the same as at "c" .~ Just (String "foo").
If we want to do nested inserts, we can use non to define a default value to be inserted:
> "{ \"a\": { \"b\": 10 } }" & key "a" . _Object . at "c" . non (Object mempty) . _Object . at "d" ?~ String "foo"
"{\"a\":{\"b\":10,\"c\":{\"d\":\"foo\"}}}"
This is a mouthful, so we can factor some parts out:
> let atKey k = _Object . at k
> "{ \"a\": { \"b\": 10 } }" & key "a" . atKey "c" . non (Object mempty) . atKey "d" ?~ String "foo"
key is based on ix, whose documentation indicates it isn't powerful enough to do what you want and points to Control.Lens.At.at. I'm pretty sure that should do the trick for you. The basic idea is that you start with the _Object prism to turn the JSON text into an object, then use at key to get a lens into that field as a Maybe. You can then change it to Just what you want.
This will work very well as long as all the objects along the path you wish to take exist. If you want to (potentially) start from nothing and create a chain of single-field objects, you will likely find things more annoying. Fortunately, you probably don't need to do this.
I am trying to use groovy for xml processing and still finding it difficult to understand its behavior. Can someone explain to me why the following program spits out 1 and 0 please? I am expecting 0 in both cases as the 'onenode' element has no children...what am I missing here?
def text = """
<characters>
<props>
<prop>dd</prop>
</props>
<character id="1" name="Wallace">
<likes>cheese</likes>
</character>
<character id="2" name="Gromit">
<likes>sleep</likes>
</character>
<onenode>help</onenode>
</characters>
"""
def xmlp = new XmlParser().parseText(text)
println xmlp.onenode[0].children().size() // prints out 1
def xmls = new XmlSlurper().parseText(text)
println xmls.onenode[0].children().size() // prints out 0
The difference is the way the parsed tree is built (both in the classes used, and how the methods work).
If we write a closure to interrogate the tree:
def dumpTypeTree = { node, prefix = '' ->
def name = node.respondsTo( 'name' ) ? "${node.name()} -- " : ''
def clazz = node.getClass().name
def txt = node.respondsTo('text') ? node.text() : node
println "${prefix}${name}${clazz} '${txt}'"
if( node.respondsTo( 'children' ) ) {
node.children().each { child ->
owner.call( child, "$prefix " )
}
}
}
When we call this method with the XmlParser constructed tree:
dumpTypeTree( new XmlParser().parseText(text) )
we get:
characters -- groovy.util.Node ''
props -- groovy.util.Node ''
prop -- groovy.util.Node 'dd'
java.lang.String 'dd'
character -- groovy.util.Node ''
likes -- groovy.util.Node 'cheese'
java.lang.String 'cheese'
character -- groovy.util.Node ''
likes -- groovy.util.Node 'sleep'
java.lang.String 'sleep'
onenode -- groovy.util.Node 'help'
java.lang.String 'help'
As you can see, the onenode node contains a String which is the text contents of that Node. And the text() call returns what we would expect.
However, calling it with XmlSlurper:
dumpTypeTree( new XmlSlurper().parseText(text) )
gives us:
characters -- groovy.util.slurpersupport.NodeChild 'ddcheesesleephelp'
props -- groovy.util.slurpersupport.NodeChild 'dd'
prop -- groovy.util.slurpersupport.NodeChild 'dd'
character -- groovy.util.slurpersupport.NodeChild 'cheese'
likes -- groovy.util.slurpersupport.NodeChild 'cheese'
character -- groovy.util.slurpersupport.NodeChild 'sleep'
likes -- groovy.util.slurpersupport.NodeChild 'sleep'
onenode -- groovy.util.slurpersupport.NodeChild 'help'
As you can see, there are no String children, and only calling text() on leaf nodes would make any sense, as outside the leaves, we get all of the text concatenated together.
Anyway, hope this explains the difference in number of children
I'm currently writing a parser for a simple programming language. It's getting there however I'm unable to parse a boolean logic statement such as "i == 0 AND j == 0". All I get back is "non exhaustive patterns in case"
When I parse a boolean expression on its own it works fine e.g. "i == 0". Note "i == 0 a" will also return a boolean statement but "i == 0 AND" does not return anything.
Can anyone help please?
Whilst the above works correctly for input such as run parseBoolean "i == 0"
As #hammar points out, you should use Text.Parsec.Expr for this kind of thing. However, since this is homework, maybe you have to do it the hard way!
The problem is in parseArithmetic, you allow anyChar to be an operator, but then in the case statement, you only allow for +, -, *, /, %, and ^. When parseArithmetic tries to parse i == 0, it uses the first = as the operator, but can't parse an intExp2 from the second =, and fails in the monad, and backtracks, before getting to the case statement. However, when you try to parse i == 0 AND j == 0, it gets the i == part, but then it thinks that there's an arithmetic expression of 0 A ND, where A is an operator, and ND is the name of some variable, so it gets to the case, and boom.
Incidentally, instead of using the parser to match a string, and then using a case statement to match it a second time, you can have your parser return a function instead of a string, and then apply the function directly:
parseOp :: String -> a -> Parser a
parseOp op a = string op >> spaces >> return a
parseLogic :: Parser BoolExp
parseLogic = do
boolExp1 <- parseBoolExp
spaces
operator <- choice [ try $ parseOp "AND" And
, parseOp "OR" Or
, parseOp "XOR" XOr
]
boolExp2 <- parseBoolExp
return $ operator boolExp1 boolExp2
parseBoolean :: Parser BoolExp
parseBoolean = do
intExp1 <- parseIntExp
spaces
operator <- choice [ try $ parseOp "==" Main.EQ
, parseOp "=>" GTorEQ
, parseOp "<=" LTorEQ
]
intExp2 <- parseIntExp
return $ operator intExp1 intExp2