[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.
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)
)
)
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?