PDA

View Full Version : Concept: Context function



Petr Schreiber
18-11-2015, 17:56
Before I try to demonstrate "how", have a look at this:


if fileCreationDate > 1.Hour.Ago then
' do something
end if


Reads great, right? And it could be built in to language with support for "context functions". What would that mean?

In case thinBasic would find construction like:
variable.something, it would of course do the usual checks for UDT members, but if it would not find any member named something, it would also check, whether there is a function, which takes TypeOf(variable) as first parameter with name something, and it would pass that variable as the parameter then. And it would work in chained way.

So for the example, all you would need to do to implement the above:


Function Hour( nValue as Number ) As Number
' -- Converts nValue to amount of milliseconds
End Function

Function Ago( timeInMilliseconds as Number ) As Number
' -- Subtracts the timeInMilliseconds from Now and returns again timeInMilliseconds
End Function


...you could call these directly:


Number oneHourAgoInMilliseconds = Ago(Hour(1))


...but also via the syntax proposed - because the parameter would be propagated via the "dot pipeline", not via parenthesis.

This is not needed within TYPEs usually, as we can define custom functions now (big THANKS to Eros), but with primitive types, such as Numbers and Strings, there is no way to "expand them".

Do you like this idea? What do you think about it?

As with all the great ideas - this is not something I invented, I saw the 1.hour.ago syntax in Ruby, and liked it very much.


Petr

ReneMiner
18-11-2015, 18:44
This would work only for functions that have 1. parameter passed ByRef...

We also could stay on current syntax and do it like this:



Function String.Unquoted([parameters]) As String

Function = Remove$( $DQ, Me)

End Function

Function String.Uppercase() As String

Function = UCase$(Me)

End Function

' Function String.Length() As Long

' Function = StrPtrLen(StrPtr(Me))

' End Function


String s = $DQ & "hello this is a quoted string" & $DQ

PrintL s
PrintL s.Unquoted
PrintL s.UpperCase

' PrintL Str$(s.Length)

' now what if this:

PrintL s.Unquoted.Uppercase
PrintL Str$( s.Unquoted.Lenght ) ' thinkeable...???



' ---???---???---???---???---???---???---

' equals this:

Function Unquoted(ByRef s As String[,Parameters]) As String

Function = Remove$( $DQ, s)

End Function

Function UpperCase(ByRef s As String) As String

Function = Ucase$(s)

End Function

String s = $DQ & "hello this is a quoted string" & $DQ

PrintL s
PrintL Unquoted(s)
PrintL Uppercase(s)

' PrintL Uppercase(Unquoted(s)) ' ???
' ... nay ... not ByRef i think since we have to refer a variable

' ... ... ... ... ... maybe allows later:

Type tFace
X As Double
Y As Double
Z As Double
col as TBGL_tRGBA ' this is a MODULES TYPE !!!
End Type


Function TBGL_tRGBA.SetValue(Byval R As Byte, Byval G As Byte, Byval B As Byte, Byval A As Byte)
Me.R = R
Me.G = G
Me.B = B
Me.A = A
End Function

Function TBGL_tRGBA.UseToDraw()

TBGL_Color Me.R, Me.G, Me.B, Me.A
End Function

Dim myFace As tFace

myFace.col.SetValue(200, 255, 127, 0)
'...
myFace.col.UseToDraw()

ErosOlmi
18-11-2015, 19:53
Proposed syntax by Petr is an advantage of those programming languages born since he beginning as Object Oriented.
Numbers are a primitive class that can be extended.
Strings are a primitive class that can be extended.
... and so on.

For programming languages born as procedural like thinBasic a syntax like 1.Hour.Ago is almost impossible unless we change the foundation of the core language.

There are some possibilities we can adopt, maybe slowing down a bit source interpretation.
I already have a hook in Core engine to scan for dotted notation almost for everything but then we need to adhere to some standards: how the language must behave?

What does it mean a number (1) followed by a term (Hour), followed by a term (Ago), followed by ... and so on ?
Is whatever meaning we can think always the same for the all similar situation?

Is 1.Divided.2 something in which the language can behave like when it encounters 1.Hour.Ago?

That's the problem I have to face when I thinBasic have to interpret a source code on the fly.

Petr Schreiber
18-11-2015, 23:05
The similar feature is "extension method" in C#. But I would not say it is necessarily OOP based, it is just syntactic sugar.

Here is proof of concept demo:


Uses "Console", "DT"

Long timeLimit = 1
'String code = "timeLimit.hours.ago" ' -- Works too
String code = "1.hours.ago"

PrintL "Now: " + DT_GetTime()
Number nValue = InterpretMe(code)

PrintL "Hour ago: " + DT_MillisecToTime(nValue)
WaitKey

Function InterpretMe( pieceOfCode As String ) As Number

String token = ConsumeToken(pieceOfCode)
String extension
Number valueNow = GetValue(token)

If IsExtendableNumeric(token) Then

While Len(Assign$(GetExtension(pieceOfCode), extension))

If Len(extension) Then
' -- Here some validation for signature, not present...

Call extension(valueNow) To valueNow
Else
Exit While
End If

Wend
End If

Return valueNow

End Function

Function ConsumeToken(ByRef pieceOfCode As String) As String
String token = IIf$(InStr(pieceOfCode, "."), Extract$(pieceOfCode, "."), pieceOfCode) ' -- This is really bad, but works for our case
pieceOfCode = Mid$(pieceOfCode, Len(token)+1)

Return token
End Function

Function IsExtendableNumeric(token As String)
Long isLiteral = token = "0" Or Val(token) <> 0
Long isVariable = VARIABLE_Exists(token) ' -- Here would be SMART test against list of numeric variables, this is too general

Return isLiteral Or isVariable
End Function

Function GetValue(token As String) As Number

If token = "0" Or Val(token) <> 0 Then
Return Val(token)
Else
Return Val(Expand$("$"+token))
End If

End Function

Function GetExtension(ByRef pieceOfCode As String) As String
If Not StartsWith(pieceOfCode, ".") Then
Return ""
Else
pieceOfCode = LTrim$(pieceOfCode, ".")
Return ConsumeToken(pieceOfCode)
End If
End Function

' --

Function Hours(ByVal x As Number) As Number
Return DT_TimeToMillisec(x+":00:00.000")
End Function

Function Minutes(ByVal x As Number) As Number
Return DT_TimeToMillisec("00:"+x+":00.000")
End Function

Function Seconds(ByVal x As Number) As Number
Return DT_TimeToMillisec("00:00:"+x+".000")
End Function

Function Ago(ByVal x As Number) As Number
Return DT_TimeToMillisec(DT_GetTime) - x
End Function



Petr