Notifications
Clear all

[Closed] function library

I’ve found that a lot of the time I use the same functions in my scripts and instead of having to keep repeating functions in my macros, I want to start building a function library that I can just call from other macros. Would I make one file with all my functions? Or lots of files? Where do I put something like this? Is scripts\Startup the place to put them?

Cheers,

Cg.

5 Replies

Hi,

I use something like this:

(
  	global ClassColor, ClassNode, ClassUV
  	
  	DotNet.LoadAssembly "$stdplugs/managed/Maxima.dll"
  	
  	fn IsLoaded val filename =
  	(
  		local path = "$stdplugs/stdscripts/Maxima"
  		if val == undefined do FileIn (path + filename)
  	)
  	
  	IsLoaded		ClassColor							"Light - Class Color.ms"
  	IsLoaded		ClassNode							"Light - Class Node.ms"
  	IsLoaded		ClassUV								"Light - Class UV.ms"
  	
  	struct ClassMaxima
  	(
  		Color							=		ClassColor,
  		Node							=		ClassNode,
  		UV							=		ClassUV,
  		Xml							=		DotNetClass "Maxima.ExtensionsXml"
  	)
  	
  	global Maxima = ClassMaxima()
  )

I think either stdscripts or scripts directory is fine.

Light

You’ll have to excuse me, I’m just a hack at this scripting stuff. I don’t understand a lot of what you have in your example function. Here’s a function that I do understand. Do I need to do anything to the code apart from saving it in one of the directories that you mention? I’m assuming that I’d save it as just an .ms file?


(
 fn TimeStampConvert duration = 
 (
 	result = stringStream ""
 	local hs, ms, ss
 	totalsecs = duration/1000
 	secs = (mod totalsecs 60) as integer
 	if secs < 10 then ss = "0" + (secs as string)
 	else ss = (secs as string)
 	totalminutes = totalsecs/60 as integer
 	mins = (mod totalminutes 60) as integer
 	if mins < 10 then ms = "0" + (mins as string)
 	else ms = (mins as string)
 	hs = totalminutes/60 as integer
 	format "%:%:%" hs ms ss to:result
 	return (result as string)	
 )
 )
 
 
1 Reply
(@denist)
Joined: 11 months ago

Posts: 0
as other guys said it's better to include your function into some structure to minimize the number of globals. If you want to call any function from macroscript the function must be defined inside macro or to be global.

you can save you function  

    fn imeStampConvert duration = (/*...*/)
    
with any .ms file and put this file into ...\stdscripts

you can put this file into …\startup but in this case you have to define TimeStampConvert as global in .mcr file where you want to cal this function from. You have to do it because the system (max) loads plug-ins (stdscripts) first, macros next, and scripts (startup) last. So at the moment of macros loading the function has to be defined.

After that the function has to be visible for macro scripts...

#1 save as .ms file into ...\stdscript:

     fn TimeStampConvert duration = 
     (
    /*	 
    	 result = stringStream ""
    	 local hs, ms, ss
    	 totalsecs = duration/1000
    	 secs = (mod totalsecs 60) as integer
    	 if secs < 10 then ss = "0" + (secs as string)
    	 else ss = (secs as string)
    	 totalminutes = totalsecs/60 as integer
    	 mins = (mod totalminutes 60) as integer
    	 if mins < 10 then ms = "0" + (mins as string)
    	 else ms = (mins as string)
    	 hs = totalminutes/60 as integer
    	 format "%:%:%" hs ms ss to:result
    	 return (result as string)
    */
    	totalsecs = duration/1000
    	result = ((dotnetclass "System.TimeSpan").Fromseconds totalsecs).ToString()
    	format "%
" result
    	result
     )
    
#2 save as .mcr file:

    macroScript my_TimeStamp
    category: "my Tests"
    (
    	TimeStampConvert (timestamp())
    )
    
#3 execute the macros


PS. Nothing is wrong with your code. I just tried to make your function a little shorter :)

Hey Chris,

    I know it's a bit off topic, but you might want to check out dateTime. It has a lot of neat methods to compare times and get info from them.
(
            time1 = (dotnetclass "system.datetime").Now
            for x in 1 to 20 do sleep 0.1 -- Kill some time
            time2 = (dotnetclass "system.datetime").Now
            timeSpan = time2.subtract time1
            
            /*
            timeSpan properties
              .Days : <System.Int32>, read-only
              .Hours : <System.Int32>, read-only
              .Milliseconds : <System.Int32>, read-only
              .Minutes : <System.Int32>, read-only
              .Seconds : <System.Int32>, read-only
              .Ticks : <System.Int64>, read-only
              .TotalDays : <System.Double>, read-only
              .TotalHours : <System.Double>, read-only
              .TotalMilliseconds : <System.Double>, read-only
              .TotalMinutes : <System.Double>, read-only
              .TotalSeconds : <System.Double>, read-only
              .MaxValue : <System.TimeSpan>, read-only, static
              .MinValue : <System.TimeSpan>, read-only, static
              .TicksPerDay : <System.Int64>, read-only, static
              .TicksPerHour : <System.Int64>, read-only, static
              .TicksPerMillisecond : <System.Int64>, read-only, static
              .TicksPerMinute : <System.Int64>, read-only, static
              .TicksPerSecond : <System.Int64>, read-only, static
              .Zero : <System.TimeSpan>, read-only, static
            */
        )
  As for having a library for your functions, you could stuff it into a struct to keep it a organize and so the functions' scope are only within the struct. In this case, you could have a struct that have functions specific for time:
struct myTimeLibrary
      (
      	 fn TimeStampConvert duration = 
      	 (
      		result = stringStream ""
      		local hs, ms, ss
      		totalsecs = duration/1000
      		secs = (mod totalsecs 60) as integer
      		if secs < 10 then ss = "0" + (secs as string)
      		else ss = (secs as string)
      		totalminutes = totalsecs/60 as integer
      		mins = (mod totalminutes 60) as integer
      		if mins < 10 then ms = "0" + (mins as string)
      		else ms = (mins as string)
      		hs = totalminutes/60 as integer
      		format "%:%:%" hs ms ss to:result
      		return (result as string)	
      	 ),
      	 
      	 fn getNextDay =
      	 (
      		( (dotnetclass "system.datetime").Now.AddDays 1).day
      	 )
      )
      
      myTimeLibrary = myTimeLibrary()
 Then maybe have another struct that's more specific to having functions about modeling. That way, it should be fairly manageable to maintain it without getting confused about where to find a function, or where to put it. Something like that!

I’ve double checked my scripts library that I’m still using and found the function which was written 7 years ago:


fn formatedTime delta msecs:off pre:"" =
(
	local sing = if delta < 0 then "-" else " "
	delta = abs delta
	local msec = mod delta 1000
	local sec = delta / 1000
	local min = sec / 60
	sec = sec - (min * 60)
	local hour = min / 60
	 min = min - (hour * 60)
	if msecs do
	(
		local smsec = ((msec as integer) as string)
		while smsec.count < 3 do smsec = "0" + smsec
	)
	
	local shour = (hour as string)
	if shour.count == 1 then shour = "0" + shour 
	
	local smin = (min as string)
	if smin.count == 1 then smin = "0" + smin
 
	local ssec = (sec as string)
	if ssec.count == 1 then ssec = "0" + ssec
 
	local str = (pre + sing + shour + ":" + smin + ":" + ssec)
	if msecs do str += ":" + smsec
	str
)

it’s naive, is not it?