Page 1 of 1

Problem using "context alias"?

Posted: Tue Feb 12, 2008 10:12 am
by ale870
Hello,

I notice a strange behavior.
Look at the following code:

Code: Select all

(context 'PIPPO)
(define (init)
	(println (string "PIPPO: " (context)))
)

(context 'PLUTO)
(println (string "A1: " (context)))
(PIPPO:init)
(println (string "A2: " (context)))
I obtain:

Code: Select all

A1: PLUTO
PIPPO: PIPPO
A2: PLUTO
It works well. Now I want to use a variable to refer to a context, so I have:

Code: Select all

(context 'PIPPO)
(define (init)
	(println (string "PIPPO: " (context)))
)

(context 'PLUTO)

(setq ctxPippo PIPPO)

(println (string "A1: " (context)))
(ctxPippo:init)
(println (string "A2: " (context)))
I got:

Code: Select all

A1: PLUTO
PIPPO: PLUTO
A2: PLUTO
Ops... something is wrong! In fact, as you can see, in this case the context inside the function "init" seems wrong!

Assigning a context to a variable is useful to create a kind of alias (usually I use full-qualified context names, and they become enough long!).

Can you tell me what's wrong? Can you find a work-around?

Thank you!

Posted: Tue Feb 12, 2008 10:25 am
by ale870
Another important point about this: sometimes I use a variable to maintain a reference to a specific context. For example:

Code: Select all

(context 'C1)
(define (f1)(println "Context C1"))

(context 'C2)
(define (f1)(println "Context C2"))

(context MAIN)

(setq ctxChoice C2) ; or... (setq ctxChoice C1)
(ctxChoice:f1)
In this case I could use the variable ctxChoice to switch between the contexts.

Posted: Tue Feb 12, 2008 1:44 pm
by ale870
Hello again!

I found a workaround, but it seems ugly! (but it works...)

Code: Select all

(context 'ThisIsMyContext)

(define (f1)
	(println (string "Context C1d: " (context) ) )
)
(setq get-f1 (f1))

(context MAIN)
(context ThisIsMyContext "get-f1")

(setq Alias ThisIsMyContext)
(context Alias "get-f1")
Basically, I used a variable defined inside the context in order to get the value of the required function. It means it is recalled from inside the context self, and the result is correct (I used a similar concept of GETTERS/SETTERS).

But I don't like it.... :-(

Posted: Tue Feb 12, 2008 4:37 pm
by ale870
This is the best solution I found. Here a "clean" example:

Code: Select all

(context 'PersonalData)

(setq _myname nil)

(define (my-name (argName nil) )
	(println (string "Context 3: " (context)))
	(if argName
		(setq _myname argName)
		_myname
	)
)

(define (get-name)
	(println (string "Context 1: " (context)))
	(my-name)
)

(define (set-name argName)
	(println (string "Context 2: " (context)))
	(my-name argName)
)

(context MAIN)

(setq ctxAlias PersonalData)

(ctxAlias:set-name "Alessandro")
(println (ctxAlias:get-name))
It seems in this way it works correctly. See the results:

Code: Select all

Context 2: MAIN
Context 3: PersonalData
Context 1: MAIN
Context 3: PersonalData
Alessandro
As you can see, even if get-name and set-name are executed in the "wrong" context, the function inside the context my-name is running in the right context.

However I think this should be fixed, since it seems an incoherent behavior.

If I'm wrong, or if you have better idea, you are welcome! :-)

Posted: Wed Feb 13, 2008 7:14 am
by ale870
One optimiziation more:

thank to newLisp and its flexibility, we can do this simple operation. Let's take this original code:

Code: Select all

(define (do-sum val1 val2)
	(println (string "Somma valori: " (+ val1 val2)))
	(+ val1 val2)
);define

(println (string "10+20=" (do-sum 10 20)))
In order to modify it to avoid context problems we can simply do this:

1) add the new function:

Code: Select all

(define (do-sum val1 val2)(_do-sum val1 val2))
2) modify the original function by adding an "_" in front of the function name. It will become:

Code: Select all

(define (_do-sum val1 val2)
	(println (string "Somma valori: " (+ val1 val2)))
	(+ val1 val2)
);define
Then the new full code will be:

Code: Select all

(define (_do-sum val1 val2)
	(println (string "Somma valori: " (+ val1 val2)))
	(+ val1 val2)
);define

(define (do-sum val1 val2)(_do-sum val1 val2))

(println (string "10+20=" (do-sum 10 20)))
Very easy.

Maybe some of you made a question: why should I have to assign a context to a variable (like an alias)? Well, there are at least two good reasons:

1) I can use a single alias to refer to different contexts (if we talk about OOP programming, we could think to "polymorphisms")

2) When I create big programs, I could find more contexts with the same name. So it means I could have some naming conflicts. In order to avoid it, I could call the contexts with a domain-specific name. For example (talking about a theorical context module to perform database access).
Basically I have "odbc.lsp" -> ODBC context.
But what happen if I will find another useful module to access to ODBC too? So I could rename original context (ODBC) as: ale870.database.odbc
(ale870 is obviously my name!).
The other module could be called:
mister.database.odbc

Well, in order to avoid to type these long context names, I need to create an alias. So:

Code: Select all

(ale870.database.odbc:connect ... )
(ale870.database.odbc:query ... )
or is better...

Code: Select all

(setq ctxODBC ale870.database.odbc)
(ctxODBC:connect ... )
(ctxODBC:query ... )
;-)

Posted: Wed Feb 13, 2008 6:32 pm
by cormullion
A good thread you have here! I'm not too skilled with contexts to be able to contribute, but your explorations are very interesting...

Posted: Wed Feb 13, 2008 9:39 pm
by ale870
Thank you! My explorations were caused by some problems I found during the development of a complex application, using CGI, for a barcode reader!
Furthermore, I like to study the different faces of a programming language, and newLISP has a lot of faces!!! :-)

Posted: Thu Feb 14, 2008 3:45 am
by Lutz
I notice a strange behavior.
The context switch always goes by context of the calling symbol, which explains the behavior you are seeing. Only for the default symbol the context switch will also work, when using an alias for the context:

Code: Select all

(define (foo:foo) (context))

(setq ctx foo)

(ctx) => foo

; but

(ctx:foo) => MAIN
The context as returned above really only is important when using the functions 'eval-string' or 'sym'. For implementig any kind of OO- polymorphism this effect has no significance and when using 'eval-string' or 'sym' it is always better to specifiy the context anyway.

For implementing polymorphism you better see the chapter "17. Object-Oriented Programming in newLISP" specifically the subchapter about the : colon operator.

Lutz

Posted: Thu Feb 14, 2008 8:18 pm
by ale870
Thank you Lutz, now everything is more clear for me!

Posted: Fri Feb 15, 2008 3:06 pm
by Lutz
In any case in version 9.3.2 the behavior is changed to:

Code: Select all

(define (foo:foo) (context)) 
(setq ctx foo) ; alias

(ctx:foo) => foo
(ctx) => foo 
which is more intuitive, and this change also gave a slight speed increase (~ 5%) when using aliases this way.

Lutz

Posted: Fri Feb 15, 2008 3:45 pm
by ale870
GREAT!!!!! I think this is the most coherent way and intuitive solution!
Thank you again!!! :-) :-) :-)