The question
Suppose you have a struct, like this:
(struct soldier (name rank serial-number) #:transparent)
(define s (soldier 'Smith 'private 100134))
How can you find out what fields soldier or s contains? Or what generic interfaces it supports, or what structure type properties it has?
Research efforts so far
(Skip this section if you already know the answer.)
I've been reading through the documentation on structs for the last few days, and I haven't been able to figure out how you're supposed to put the pieces together. I'm probably just missing some elementary tidbit of information that goes without saying to people who know Racket.
The chapter on Reflection and Security has a section "Structure Inspectors", which says:
An inspector provides access to structure fields and structure type information without the normal field accessors and mutators.
but I haven't understood how to get an inspector to provide that.
struct-info and struct-type-info provide some information, but not field names, interfaces, properties, etc.:
> (struct-type-info struct:soldier)
'soldier
3
0
#<procedure:soldier-ref>
#<procedure:soldier-set!>
'(0 1 2)
#f
#f
struct->vector and struct->list provide access to an instance's contents and the above data, but that's all:
> (struct->vector s)
'#(struct:soldier Smith private 100134)
If you could show me an example of how to inspect a struct type to see what's in it, that would probably clarify whatever soon-to-be-obvious-in-hindsight thing I'm not seeing here.
The field names are not available at run time. However you can at expansion time use syntax-local-value on the struct name to get some information.
A quick example:
#lang racket
(require (for-syntax racket/struct-info))
(struct foo (a b))
(begin-for-syntax
(display (extract-struct-info (syntax-local-value #'foo))))
Update
In this example:
#lang racket
(require (for-syntax racket/struct-info))
(struct foo (a [b #:mutable] c))
(begin-for-syntax
(display (extract-struct-info (syntax-local-value #'foo))))
The list of identifiers for mutators is: (#f #<syntax:4:8 set-foo-b!> #f).
That is only the second field is mutable.
The information is available at expansion time, so you can transfer the information to runtime by calling a macro that expands into a definition like (define info '(#f set-foo-b! #f) or similar.
Related
I'm writing a class named "MyObject".
one of the class methods is:
addTo: aCodeString assertType: aTypeCollection
when the method is called with aCodeString, I want to add (in runtime) a new method to "MyObject" class which aCodeString is it's source code and inject type checking code into the source code.
for example, if I call addTo: assertType: like that:
a := MyObject new.
a addTo: 'foo: a boo:b baz: c
^(a*b+c)'
assertType: #(SmallInteger SmallInteger SmallInteger).
I expect that I could write later:
answer := (a foo: 2 boo: 5 baz: 10).
and get 20 in answer.
and if I write:
a foo: 'someString' boo: 5 baz: 10.
I get the proper message because 'someString' is not a SmallInteger.
I know how to write the type checking code, and I know that to add the method to the class in runtime I can use 'compile' method from Behavior class.
the problem is that I want to add the type checking code inside the source code.
I'm not really familiar with all of squeak classes so I'm not sure if I rather edit the aCodeString as a string inside addTo: assertType: and then use compile: (and I don't know how to do so), or that there is a way to inject code to an existing method in Behavior class or other squeak class.
so basically, what I'm asking is how can I inject string into an existing string or to inject code into an existing method.
There are many ways you could achieve such type checking...
The one you propose is to modify the source code (a String) so as to insert additional pre-condition type checks.
The key point with this approach is that you will have to insert the type checking at the right place. That means somehow parsing the original source (or at least the selector and arguments) so as to find its exact span (and the argument names).
See method initPattern:return: in Parser and its senders. You will find quite low level (not most beautiful) code that feed the block (passed thru return: keyword) with sap an Array of 3 objects: the method selector, the method arguments and the method precedence (a code telling if the method is connected to unary, binary or keyword message). From there, you'll get enough material for achieving source code manipulation (insert a string into another with copyReplace:from:to:with:).
Do not hesitate to write small snippets of code and execute in the Debugger (select code to debug, then use debug it menu or ALT+Shift+D). Also use the inspectors extensively to gain more insight on how things work!
Another solution is to parse the whole Abstract Syntax Tree (AST) of the source code, and manipulate that AST to insert the type checks. Normally, the Parser builds the AST, so observe how it works. From the modified AST, you can then generate new CompiledMethod (the bytecode instructions) and install it in methodDictionary - see the source code of compile: and follow the message sent until you discover generateMethodFromNode:trailer:. This is a bit more involved, and has a bad side effect that the source code is now not in phase with generated code, which might become a problem once you want to debug the method (fortunately, Squeak can used decompiled code in place of source code!).
Last, you can also arrange to have an alternate compiler and parser for some of your classes (see compilerClass and/or parserClass). The alternate TypeHintParser would accept modified syntax with the type hints in source code (once upon a time, it was implemented with type hints following the args inside angle brackets foo: x <Integer> bar: y <Number>). And the alternate TypeHintCompiler would arrange to compile preconditions automatically given those type hints. Since you will then be very advanced in Squeak, you will also create special mapping between source code index and bytecodes so as to have sane debugger and even special Decompiler class that could recognize the precondition type checks and transform them back to type hints just in case.
My advice would be to start with the first approach that you are proposing.
EDIT
I forgot to say, there is yet another way, but it is currently available in Pharo rather than Squeak: Pharo compiler (named OpalCompiler) does reify the bytecode instructions as objects (class names beginning with IR) in the generation phase. So it is also possible to directly manipulate the bytecode instructions by proper hacking at this stage... I'm pretty sure that we can find examples of usage. Probably the most advanced technic.
today on "adventures in functional programming with lenses" our hero attempts to define a prism over a list element that may or may not exist.
It's a bit tricky to explain, so to avoid the X, Y problem I'll give the actual use-case in all its glory.
I'm writing a Text editor in Haskell called Rasa, the whole idea is that it's extremely extensible, and that means most functionality is written as extensions. Since it's a core principle, extensions ALSO depend on other extensions, so I needed a way to store their state centrally such that all extensions depending on an extension could access its current 'extension state'. Of course the types of these states is not known to the core of the editor, so at the moment I'm storing a list of Dynamic values. When the extension stores the state it converts to a Dynamic, then it can be extracted later via a prism like so:
data Store = Store
{ _event :: [Event]
, _editor :: E.Editor
, _extState :: [Dynamic]
}
ext :: Typeable a => Traversal' Store a
ext = extState.traverse._Dynamic
So now ext is a polymorphic Traversal that essentially operates over only the Dynamics that 'match' the type in question (if you set to it it'll replace values of the same type, if you 'get' from it, it acts as a traversal over the Dynamics that match the type of the outbound value). If that seems like magic, it basically is...
BTW, I'd love to have exactly 1 copy of a given Extension's state object in the list at any time.
So getting and setting is actually working fine IFF there's already a value of the proper type in the list, my question is how can I make a version of this Traversal such that if a value of the proper type is in the list that it will replace it (and getting works as expected), but that will ADD a value to the list if the traversal is SET to and there's NO matching element in the list. I understand that Traversal's aren't supposed to change the number of elements that they're traversing, so perhaps this needs to be a prism or lens over the list itself?
I understand this is really confusing, so please ask clarifying questions :)
As for things I've taken a look at already, I was looking at prefixed and _Cons as possible ways to do this, but I'm just not quite sure how to wire it up. Maybe I'm barking up the wrong tree entirely.
I could perhaps add a default value to the end of the traversal somehow, but I don't want to require Monoid or Default so I can't conjure up elements from nowhere (and I only want to do it when SETTING).
I'm also open to discussions about whether this is actually the proper way to store this state at all, but it's the most elegant of solutions I've found so far (though I know typecasting at run time is sub-optimal). I've looked into the Vault type, but passing keys around didn't really work well when I tried it (and I imagine it has similar type-casting performance issues).
Cheers! Thanks for reading.
I think the list of extensions is not proper solution for you. I would be added something like _extState :: Map TypeRep Ext where data Ext = forall a. Ext a. Then I would be added the lens:
ext :: forall a . Typeable a => Lens' Store (Maybe a)
ext = _extState . at (typeRep (Proxy :: Proxy a)) . mapping coerce
where
coerce = iso (\(Ext x) -> unsafeCoerce x) Ext
This lens does like at. So you can simply get/set your extensions.
But there is one limitation, all extensions must be of different types.
I have an extern API sending info to my Prolog application and I found a problem creating my facts.
When the information received is extensive, Prolog automatically adds ' (single quotes) to that info.
Example: with the data received, the fact I create is:
object(ObjectID,ObjectName,'[(1,09:00,12:00),(2,10:00,12:00)]',anotherID)
The fact I would like to create is
object(ObjectID,ObjectName,[(1,09:00,12:00),(2,10:00,12:00)] ,anotherID)
without the ' before the list.
Does anyone know how to solve this problem? With a predicate that receives '[(1,09:00,12:00),(2,10:00,12:00)]' and returns [(1,09:00,12:00),(2,10:00,12:00)]?
What you see is an atom, and you want to convert it to a term I think.
If you use swi-prolog, you can use the builtin term_to_atom/2:
True if Atom describes a term that unifies with Term. When Atom is instantiated, Atom is parsed and the result unified with Term.
Example:
?- term_to_atom(X,'[(1,09:00,12:00),(2,10:00,12:00)]').
X = [ (1, 9:0, 12:0), (2, 10:0, 12:0)].
So at the right hand side, you enter the atom, at the left side the "equivalent" term. Mind however that for instance 00 is interpreted as a number and thus is equal to 0, this can be unintended behavior.
You can thus translate the predicate as:
translate(object(A,B,C,D),object(A,B,CT,D)) :-
term_to_atom(CT,C).
Since you do not fully specify how you get this data, it is unknown to me how you will convert it. But the above way will probably be of some help.
I need to create a function f:: Log->[String] that does that (((o, i ,d),s) = [(o, i ,d)]
type Log = (Plate, [String])
type Plate = (Pin, Pin, Pin)
type Pin = (Char, Int)
If you're on a page like this, click "Source" on the fir right side, next to the function that you're interested in.
If you need to look up a function, Hayoo! and Hoogle will link you to documentation pages like the one above.
An important thing to note, though is that show doesn't have one definition. show is a function defined for all data types in the Show (with a capital "S") typeclass. So for example, here is the full source for the Show typeclass. Show is defined within the typeclass as just show :: a -> String. But if you search for "instance Show Bool" or "instance Show Int", you'll find specific definitions.
For the second part of your question, the easiest way to get a show function for a new type is to simply write deriving (Show) below it. For example,
data Foo = Foo Int Int
deriving (Show)
Now I can use show on data with type Foo.
g :: Log -> [String]
g (plate, _) = [show plate]
Use hoogle to find this sort of information.
Example: http://www.haskell.org/hoogle/?hoogle=show
Once you've found the function you'd like in the list, click and there you'll find a Source link on the right hand side of the page.
NB this is an answer to the original question:
Where can I see the codes of the predefined functions in haskell ?? Mainly the function SHOW?
It's true that you can use Hoogle to search for functions defined in the Prelude (and other modules), but the source code itself is located at Hackage.
Hackage is a database of Haskell packages. You can download new packages from it, and also view the Haddock documentation for every package in the database.
This is the Haddock page for the standard Prelude. It documents the type classes, data types, types, and top-level functions exported by the Prelude module. To the right of each definition header is a link that says "Source". You can click this to be taken to an online copy of the source code for the module you're viewing.
On preview, you're now asking a different question entirely, and on preview again in fact the original question has been edited out of this post.
Your new question is unclear, but this solution will work to produce the output in your example.
> [fst ((('O',0),('I',0),('D',1)),"O->D")]
[(('O',0),('I',0),('D',1))]
I think you're using list notation instead of double quotes to identify Strings, by the way, so I fixed that around 0->D above. So you might also try this instead.
> show (fst ((('O',0),('I',0),('D',1)),"O->D"))
"(('O',0),('I',0),('D',1))"
This works because you have only defined type synonyms (by using type in your declarations instead of data) on data structures which already have Show instances.
I want to see if I can map Racket structure fields to columns in a DB.
I've figured out how to extract accessor functions from structures in PLT scheme using the fourth return value of:
(struct-type-info)
However the returned procedure indexes into the struct using an integer. Is there some way that I can find out what the field names were at point of definition? Looking at the documentation it seems like this information is "forgotten" after the structure is defined and exists only via the generated-accessor functions: (<id>-<field-id> s).
So I can think of two possible solutions:
Search the namespace symbols for ones that start with my struct name (yuk);
Define a custom define-struct macro that captures the ordered sequence of field-names inside some hash that is keyed by struct name (eek).
I think something along the lines of 2. is the right approach (define-struct has a LOT of knobs and many don't make sense for this) but instead of making a hash, just make your macro expand into functions that manipulate the database directly. And the syntax/struct library can help you do the parsing of the define-struct form.
The answer depends on what you want to do with this information. The thing is that it's not kept in the runtime -- it's just like bindings in functions which do not exist at runtime. But they do exist at the syntax level (= compile-time). For example, this silly example will show you the value that is kept at the syntax level that contains the structure shape:
> (define-struct foo (x y))
> (define-syntax x (begin (syntax-local-value #'foo) 1))
> (define-syntax x (begin (printf ">>> ~s\n" (syntax-local-value #'foo)) 1))
>>> #<checked-struct-info>
It's not showing much, of course, but this should be a good start (you can look for struct-info in the docs and in the code). But this might not be what you're looking for, since this information exists only at the syntax level. If you want something that is there at runtime, then perhaps you're better off using alists or hash tables?
UPDATE (I've skimmed too quickly over your question before):
To map a struct into a DB table row, you'll need more things defined: at least hold the DB and the fields it stand for, possibly an open DB connection to store values into or read values from. So it looks to me like the best way to do that is via a macro anyway -- this macro would expand to a use of define-struct with everything else that you'd need to keep around.