views:

56

answers:

2

When I start up an R3 Alpha 99 session, and enter this as the first command, I get an error:

>> is-email-addr: get bind to-word "email?" bind? 'system
** Script error: email? is not in the specified context
** Where: bind
** Near: bind to-word "email?" bind? 'system

But if I quit, restart and instead execute a test to prove that the email? primitive lives in global context like the system object, the test itself makes my alias work:

>> equal? bind? 'system bind? 'email?
== true

>> is-email-addr: get bind to-word "email?" bind? 'system
>> is-email-addr [email protected]
== true

What's going on, here?

+2  A: 

Binding doesn't add words to the context, unless you tell it to - you have to use bind/new.

>> get bind/new to-word "email?" bind? 'system

But your question shows a couple misconceptions about the R3 binding model. There is no single global context in R3, not like R2. The word 'system in your example is bound to the task-local shared script context, aka the user context. And getting the right value for words in the user context often means importing them from the system context, or the exports of the loaded modules, a process known as interning the words.

To do what you apparently want to do here, it would be best for you to use intern, like this:

>> get first intern to-block "email?"

The to-block is used because intern is generally used to operate on whole blocks of code. I'll fix it in the next version so it can work on words directly as well; then you will be able to do this:

>> get intern to-word "email?"

I hope this helps.

Why aren't you using the word directly? Using strings and converting to words later has so much overhead, which is usually unnecessary.

Brian Hawley
On a fresh interpreter, *get bind/new to-word "email?" bind? 'system* doesn't work either. And in fact, running that command causes your intern example to fail subsequently. But if the interpreter is restarted after the bind then the INTERN example works, as does LOAD. Whyzzat?
Hostile Fork
Reason for not using word directly, as mentioned on AltME, is trying to write a simple remapper that takes *"em"* and *'email!* and abbreviates to create *em?* as an alias for *email?* and *em!* for *email!*. This requires exploiting the string relationship between the words.
Hostile Fork
"Whyzzat?" Because when you run that command you add the word 'email? to the user context, with no value assigned to it, and don't migrate the value from the system or export contexts. When you run INTERN later (LOAD calls INTERN), it sees the existing word in the user context and doesn't override it because it is a user word. The user context is not, by default, filled with the contents of the system and export contexts - it gets filled on demand. If you want the system values it's really better to use INTERN from the beginning.
Brian Hawley
+1  A: 

If you really insist on using "email?" string instead of an 'email? word, then the simplest way for you to obtain a word from it while not observing any strangenesses would be to use the LOAD function as follows:

is-email-addr: get bind load "email?" bind? 'system
Ladislav