B4J Question B4J v9.10 BETA is available for download

Erel

Administrator
Staff member
Licensed User
It has been a while since the B4X language itself received new features. This update adds two new language features:

- IIf - Inline If, also called ternary if as it is an operator with three arguments.
B4X:
Label1.Text = IIf(EditText1.Text <> "", EditText1.Text, "Please enter value")
IIf is mostly equivalent to this sub:
B4X:
Sub PseudoIIf (Condition As Boolean, TrueValue As Object, FalseValue As Object) As Object
 If Condition = True Then Return TrueValue Else Return FalseValue
End Sub
Unlike this sub, the IIf keyword will only evaluate the relevant expression. This means that this code will work properly:
B4X:
Return IIf(List1.Size > 0, List1.Get(0), "List is empty")
(There is another minor difference related to the return type. If it is set explicitly with the new As method, the compiler will avoid casting the values to Object and back to the target type. This is only significant in very tight and long loops).

- As - Inline casting. Allows inline casting from one type to another. Some examples:
B4X:
Dim Buttons As List = Array(Button1, Button2, Button3, Button4, Button5)
Dim s As String = Buttons.Get(2).As(B4XView).Text
Buttons.Get(2).As(B4XView).Text = "abc"
Dim j As String = $"{
data: {
key1: value1,
complex_key2: {key: value2}
},
items: [0, 1, 2]
}"$

Dim parser As JSONParser
parser.Initialize(j)
Dim m As Map = parser.NextObject
Dim value1 As String = m.Get("data").As(Map).Get("key1")
Dim value2 As String = m.Get("data").As(Map).Get("complex_key2").As(Map).Get("key")
Dim FirstItemInList As String = m.Get("items").As(List).Get(0)
For Each item As Int In m.Get("items").As(List)
    Log(item)
Next
Root.GetView(8).As(WebView).LoadUrl("https://www.google.com")
And:
B4X:
Button1.As(JavaObject).RunMethod("setMouseTransparent", Array(True))
It can also be used with numbers, which is especially useful when calling external APIs with JavaObject, as the types need to be exact:
B4X:
Log(Me.As(JavaObject).RunMethod("sum", Array((10).As(Float), (20).As(Double))))
'equivalent to:
Dim jme As JavaObject = Me
Dim f As Float = 10
Dim d As Double = 20
Log(jme.RunMethod("sum", Array(f, d)))

#if Java
public double sum(float n1, double n2) {
return n1 + n2;
}
#End If
This update also makes it possible to define custom class templates inside b4xlibs. You can see an example in B4XPages.b4xlib. With this feature, it will be possible to add B4XPages classes in B4i.
B4i update with these features and more will be released next week.

Download link:
 

rbghongade

Active Member
Licensed User
Great! B4J is evolving into a highly sophisticated language! Happy to be a part of B4X family!
Just one wish of mine is left still: drawing lines , circles , rectangles directly without code( I write this knowing that many forum friends will rebuke me for this wish)
 
Last edited:

Enrique Gonzalez R

Well-Known Member
Licensed User
The IDE marks an error when i write:

B4X:
cmbCuenta.Tag.As(dataTable)
The datatable class is a b4x class.

it doesnt show any error when i do:

B4X:
cmbCuenta.Tag.As(String)
is it an error? or it only support the core library?
 

Erel

Administrator
Staff member
Licensed User
Example for clarification?
B4X:
Dim n As Long = DateTime.Now
Dim count As Int
For i = 1 To 100000000
    count = count + IIf(True, 3, 3)
Next
Log(count)
Log(DateTime.Now - n)
Dim n As Long = DateTime.Now
Dim count As Int
For i = 1 To 100000000
    count = count + IIf(True, 3, 3).As(Int)
Next
Log(count)
Log(DateTime.Now - n)
The datatable class is a b4x class.

it doesnt show any error when i do:
This is indeed a bug. I will release a new beta next week.
There is also a bug with assignments of fields using As (properties will work). It will also be fixed in the next beta.
 

Daestrum

Well-Known Member
Licensed User
@agraham It looks like it's the underlying java code that changes.
B4X:
count = count + IIf(True, 3, 3)
becomes
B4X:
_count = (int) (_count+(double)(BA.ObjectToNumber(((anywheresoftware.b4a.keywords.Common.True) ? ((Object)(3)) : ((Object)(3))))));
whereas
B4X:
count = count + IIf(True, 3, 3).As(Int)
becomes
B4X:
_count = (int) (_count+(((anywheresoftware.b4a.keywords.Common.True) ? ((int) (3)) : ((int) (3)))));
which results in a nearly 60x decrease in processing time.
 
Last edited:

JordiCP

Well-Known Member
Licensed User
Just gave it a go and the new additions are great!

I observed some things. Perhaps they are already detected, or intended to be that way, just pointing them out.

-- As( )--

(not sure if it is the same you mention in #8)
The contextual help does not show the ".As(..)" unless we surround the variable with brackets. This was already seen in the examples for numbers and made sense, but is a bit strange for variables. Anyhow, once the sentence is completed, it is accepted by the IDE.
B4X:
Dim a as Float = 1.1
Dim b as int  = a.As(int) + 3          '<-- When typing "a.", contextual help does not show the '.As' as an option
Dim bcas int = (a).As(int) + 4          '<-- When typing "(a).", contextual help DOES show the '.As' as an option

-- IIf((,,) ---

I tested if it could be used as a ternary conditional execution besides of conditional assignment.
B4X:
IIf(condition, doThis, doThat)
As I understand it, it is "nearly" the same, since the corresponding TrueValue or FalseValue is evaluated, so they can be methods. Everything works ok in this scenario, except that the compiler expects the final result to be assigned to a variable which makes it less intuitive for conditional execution (without final assignment), contrarily to what the 'equivalent' PseudoIIf Sub would do

B4X:
Sub Button1_Click

    Dim operation As String = "sum"
    Dim a() As Int = Array As Int(1,2,3,4)

'==============================================================
' Conditional assignment: the TrueValue and FalseValue parameters are expressions or results of methods that do return values
'==============================================================
    ' This works because the result of IIf is assigned to 'res'.
    Dim res As Int = IIf(operation = "sum", increase(10), decrease(10) )

    ' This does not compile because the result of IIf is not finally assigned to anything.
    IIf(operation = "sum", increase(10), decrease(10) )

'==============================================================
' Conditional execution. The TrueValue and FalseValue parameters are results of methods that do not necessarily return values
'==============================================================
    ' This does work because increaseAll() and decreaseAll() don't return anything (I guess internally is Null), and the final result (Null) is assigned to an Object
    Dim res2 As Object = IIf(operation = "sum", increaseAll(a), decreaseAll(a) )

    ' This does not compile because the IIf result is not assigned to anything
    IIf(operation = "sum", increaseAll(a), decreaseAll(a) )

    ' BUT, this is accepted, I guess because Subs that return values are accepted to be called without assignment.
    PseudoIIf(operation = "sum", increaseAll(a), decreaseAll(a))

End Sub

Sub PseudoIIf (Condition As Boolean, TrueValue As Object, FalseValue As Object) As Object
  If Condition = True Then Return TrueValue Else Return FalseValue
End Sub

Sub increase(val as int) as int
   return val+1
End Sub

Sub decrease(val as Int) As Int
   return val-1
End Sub

Sub increaseAll(vals() As Int)
    For k=0 To vals.Length-1
        vals(k)=vals(k)+1
    Next
End Sub

Sub decreaseAll(vals() As Int)
    For k=0 To vals.Length-1
        vals(k)=vals(k)-1
    Next
End Sub
As said, I'm not sure that the later is itself a bug, but, since the IIf operator is so near to be something that can also be used as conditional execution (without forced final assignment), I thought it was worth mentioning.👀
 
Last edited:

Erel

Administrator
Staff member
Licensed User
v9.10 beta #2 is available for download. It fixes the issues reported above.

Everything works ok in this scenario, except that the compiler expects the final result to be assigned to a variable which makes it less intuitive for conditional execution (without final assignment), contrarily to what the 'equivalent' PseudoIIf Sub would do
IIf is built as an operator and it is not a complete code block by itself. You can use 'single line if' in such cases instead.
 

Enrique Gonzalez R

Well-Known Member
Licensed User
hi! found another issue or may be i am wrong in the syntax.
How do i make an inline casting to an array?

B4X:
    Dim tag() As Object = txt.Tag
    txt.Tag.As(Object()) 'gives an error and doesnt recognice it as an array
 

William Lancee

Active Member
Licensed User
Casting is not the same as conversion. The content is not changed, only treated differently.
B4X:
    Dim complexTag() As Object = Array("flowers", Array(1,2,3), True)
    Log(complexTag(0).As(String))
 

Enrique Gonzalez R

Well-Known Member
Licensed User

agraham

Expert
Licensed User
i am not casting an array to a different type, i am casting an object (txt.tag) to an array of objects.
Tag() is already an array of Objects. The cast is unnecessary even if it did work.
EDIT: OK I see now that you intended the two lines to be readseaparatley but equivalently. The As keyword assumes it is dealing with a single value. and does different things depending upon whether it is a primitive or reference value. It is not applicable to arrays of values.
 
Top