Problem using "context alias"?

Started by ale870, February 12, 2008, 02:12:47 AM

Previous topic - Next topic

ale870

Hello,



I notice a strange behavior.

Look at the following code:


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

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


I obtain:


A1: PLUTO
PIPPO: PIPPO
A2: PLUTO


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


(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:


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!
--

ale870

#1
Another important point about this: sometimes I use a variable to maintain a reference to a specific context. For example:


(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.
--

ale870

#2
Hello again!



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


(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.... :-(
--

ale870

#3
This is the best solution I found. Here a "clean" example:



(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:



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! :-)
--

ale870

#4
One optimiziation more:



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



(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:


(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:



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


Then the new full code will be:


(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:


(ale870.database.odbc:connect ... )
(ale870.database.odbc:query ... )


or is better...


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


;-)
--

cormullion

#5
A good thread you have here! I'm not too skilled with contexts to be able to contribute, but your explorations are very interesting...

ale870

#6
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!!! :-)
--

Lutz

#7
QuoteI 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:


(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

ale870

#8
Thank you Lutz, now everything is more clear for me!
--

Lutz

#9
In any case in version 9.3.2 the behavior is changed to:


(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

ale870

#10
GREAT!!!!! I think this is the most coherent way and intuitive solution!

Thank you again!!!  :-)  :-)  :-)
--