Thanks, Jameson,

I should say in this case it is obvious the function would be better and I 
agree, this was a case I made myself to see if it could be done. The reason 
being, I'm writing a type, the composition of which could be extended by 
the user to contain other information (I'm working with a data format and 
file format(s) for phylogenetic data which is often non standard). So I 
made the base type extendible, and now I'm trying to get the stuff that 
reads or writes to file to be extendible. I'm currently working on the 
writing stuff to file, and what I've done got is a function which will 
write the data to file, including the extra user extended data, as long as 
the user has provided a method for representing it as a string, and so I 
thought providing some macro's to make defining such methods more quick and 
painless to write for the user, but perhaps providing a set of 
sub-functions would be better. Hence the INN macro, so you don't have to 
write lines checking it's not nothing every time (which I know 
shouldn't.... happen, but again, this is a bit of a contrived case to try 
and see if it could/should be done this way. I also had an idea for writing 
a macro which generated the entire function for the user given some basic 
information, but baby steps first. Strikes me a lot of times I figure a 
macro would be good for something, a function can do the same job.    

Best,
Ben.



 

On Friday, April 18, 2014 6:38:14 AM UTC+1, Jameson wrote:
>
> disclaimer: I would use a function, not a macro for this purpose: 
> INN( outstring, value ) = value !== nothing ? "$outstring$value" : 
> outstring 
> INN(outstring, x.value) 
>
> it is simpler, and gives up nothing in exchange for actually being 
> readable and versatile 
>
> but assuming you had a more interesting use case: when you expand the 
> macro as written, the result is: 
> "$string$value", with string=:outstring and value=:(x.value), exactly 
> as you specified: "outstringx.value" 
>
> but you want the string before interpolation (note that I'm switching 
> to the functional form of string interpolation because it is easier to 
> read in macro form), so we need this complicated thing to make a macro 
> that is actually just a function: 
> macro INN(str, val) 
>   :( v = $(esc(val)); s = $(esc(str)); v != nothing ? string(v, s) : s ) 
> end 
>
> but the better way to write that is: 
> INN( outstring, value ) = value !== nothing ? "$outstring$value" : 
> outstring 
> macro INN(str, val) 
>   :( INN($(esc(str)), $(esc(val))) ) 
> end 
>
> why is this better? it's easier to read, write, and debug (also, 
> because it makes it obvious that you should not be using a macro for 
> this) 
>
> finally, there's the even cleaner options: 
>   outstring = "<MeltTemp>$(x.value!==nothing?x.value:"")</MeltTemp>" 
>
> or, using multiple dispatch -- my favorite option (excellent API for 
> future extensibility): 
>   mystr(::Nothing) = "" 
>   mystr(x) = x 
>   outstring = "<MeltTemp>$(mystr(x))</MeltTemp>" 
>
> note that since in your type, you have value::Int, so value will 
> always be an Int, never another type (like nothing), so it's a 
> pointless test 
>
> final note, string concatenation using $ or * or string (all of which 
> are exactly equivalent) is going to be slow compared to making an 
> IOBuffer, printing / writing / or showing all of your text to the 
> buffer, then calling takebuf_string(iobuf) at then end 
>
> On Thu, Apr 17, 2014 at 11:38 PM, Ben Ward 
> <axolotl...@gmail.com<javascript:>> 
> wrote: 
> > Hi Is it possible to use macros inside o functions in Julia if they are 
> > expanded at compile time as the manual says? I've been playing with a 
> toy 
> > type: 
> > 
> > type MeltingTemperature 
> >   value::Int 
> > end 
> > 
> > 
> > 
> > 
> > myvar = MeltingTemperature(56) 
> > 
> > 
> > and say I want to make a function that write it out as an XML string: 
> > "<MeltingTemperature>56</MeltingTemperature> 
> > 
> > Now I want to make a function that constructs that string by 1). Adding 
> the 
> > open tag 2). Checking the temperature is not nothing and if it is not, 
> > including it in the string. 3). add the closing tag. 
> > 
> > I figured step 2 would be a good candidate for a macro for a larger type 
> as 
> > checking each value is not nothing would be tedious. So: 
> > 
> > macro INN(string, value) 
> >   value != nothing ? "$string$value" : "$string" 
> > end 
> > 
> > 
> > function writePhyXML(x::MeltingTemperature) 
> >   outstring = "<MeltTemp>" 
> >   outstring = @INN outstring x.value; 
> >   outstring = "$(outstring)</MeltTemp>" 
> >   outstring 
> > end 
> > 
> > 
> > I figured the macro would be expanded and the function definition would 
> > become: 
> > 
> > function writePhyXML(x::MeltingTemperature) 
> >   outstring = "<MeltTemp>" 
> >   outstring = x.value != nothing ? "$outstring$x.value" : "$outstring" 
> >   outstring = "$(outstring)</MeltTemp>" 
> >   outstring 
> > end 
> > 
> > 
> > But results in "outstringx.value</MeltTemp>" 
> > 
> > Is it possible to do this with macro's? I had presumed it is. 
> > 
> > (I know it's possible by just using a sub function, but I wanted to see 
> how 
> > to try and use macros to generate code for function definitions if 
> > possible.) 
> > 
> > Thanks, 
> > Ben. 
>

Reply via email to