I am trying to figure out recursion for OCaml in the context of an object's method. I have tried the following code but can't seem to get it to compile.
class foo =
object (self)
method loopTest =
let rec doIt x =
Printf.printf "%d\n" x;
if x>1 then doIt (x+1)
end;;
How do I create a recursive function of this sort within a method?
Revised code:
class foo =
object (self)
method loopTest =
let rec doIt x =
Printf.printf "%d\n" x;
if x<10 then doIt (x+1) in doIt 0
end;;
You still need to call doIt in your loopTest method. let just defines doIt, just like method just defines a method, and does not call it. The compiler detects this because it doesn't know what to return from loopTest (like a method that does not have return type void, but has no implementation in C# or Java).
Also, you're in for an infinite loop with this code, maybe if x>1 then doIt (x-1) followed by doIt 100 is a better idea.
My OCaml is rusty, but I don't think let evaluates to what it bound. If you want testLoop to call doIt, tack on a in doIt or similar.
Two infinite loops in the same code ;), you should learn about Iterators I guess;)
Related
I encountered an unfamiliar pattern of initialization from Objective-C that I'm struggling to replicate in Swift.
Objective-C
In the example code, they defined a C struct such as this (abbreviated, original here):
struct AQPlayerState {
AudioFileID mAudioFile;
}
Here's an example that uses AQPlayerState:
AQPlayerState aqData; // 1
OSStattus result =
AudioFileOpenURL(
audioFileURL,
fsRdPerm,
0,
&aqData.mAudioFile // 2
);
The key takeaway from above is that aqData currently has uninitialized properties, and AudioFileOpenURL is initializing aqData.mAudioFile on it's behalf.
Swift
I'm trying to replicate this behaviour in Swift. Here's what I've tried so far:
Models:
class Person {
var name: String
init(name: String) {
self.name = name
}
}
class Foo {
var person: Person?
}
My idea was to replicate the Objective-C code by passing a reference of Foo.person into a function that would instantiate it on it's behalf.
Initialization Function:
func initializeWithBob(_ ptr: UnsafeMutablePointer<Person?>) {
ptr.pointee = Person(name: "Bob")
}
initializeWithBob takes a pointer to an address for a Person? type and initializes it with a Person(name: "Bob") object.
Here's my test code:
let foo = Foo()
let ptr = UnsafeMutablePointer<Person?>.allocate(capacity: 1)
ptr.initialize(to: foo.person)
defer {
ptr.deinitialize()
ptr.deallocate(capacity: 1)
}
initializeWithBob(ptr)
print(foo.person) // outputs nil
initializeWithBob failed to "install" an instance of type Person in my Foo instance. I presume some of my assumptions are wrong. Looking for help in correcting my assumptions and understanding of this situation.
Thanks in advance!
You can achieve what you are looking for via withUnsafeMutablePointer(to:_:) like so:
let foo = Foo()
withUnsafeMutablePointer(to: &foo.person) { (ptr) -> Void in
initializeWithBob(ptr)
}
print(foo.person!.name) // outputs Bob
However, I wouldn't recommend this approach. IMHO it makes more sense to wrap the APIs you are working with in a C function that you can make 'nice' to call from Swift. The problem with your current approach is that this type of Swift is hard to read for Swift developers and also hard to read for Audio Toolbox developers.
#kelvinlau Is this what you were thinking of trying to achieve?
func initializeWithBob(_ ptr: UnsafeMutablePointer<Foo>) {
ptr.pointee.person = Person(name: "Bob")
}
let foo = Foo()
let ptr = UnsafeMutablePointer<Foo>.allocate(capacity: 1)
ptr.initialize(to: foo)
initializeWithBob(ptr)
print(foo.person?.name ?? "nil")
ptr.deinitialize()
ptr.deallocate(capacity: 1)
print(foo.person?.name ?? "nil")
The code pattern you have in Objective-C is for out parameters, that is parameters which return a value, or in out parameters, that is parameters which both pass a value in and return one. Objective-C does not directly support these so pointers are used to produce the semantics.
Swift has in out parameters indicated by the keyword inout in the function declaration. Within the function an assignment to an inout parameters effectively assigns a value to the variable that was passed as the argument. At the function call site the variable must be prefixed by & to indicate it is the variable itself and not its value which is effectively being passed.
Keeping your Person and Foo as is your function becomes:
func initializeWithBob(_ ptr: inout Person?)
{
ptr = Person(name: "Bob")
}
and it may be used, for example, like:
var example = Foo()
initializeWithBob(&example.person)
Using inout in Swift is better than trying to build the same semantics using pointers.
HTH
Note: You can skip this unless you are curious
"Effectively" was used a few times above. Typically out parameters are implemented by the parameter passing method call-by-result, while in out use call-by-value-result. Using either of these methods the returned value is only assigned to the passed variable at the point the function returns.
Another parameter passing method is call-by-reference, which is similar to call-by-value-result except that each and every assignment to the parameter within the function is immediately made to passed variable. This means changes to the passed variable may be visible before the function returns.
Swift by design does not specify whether its inout uses call-by-value-result or call-by-reference. So rather than specify the exact semantics in the answer "effectively" is used.
This works because Iterator implements rev() where self is a DoubleEndedIterator:
let vec: Vec<i32> = Vec::new();
for x in vec.iter().rev() {
//Do stuff
}
However, if I change vec.iter().rev() to &vec.rev() it won't compile because:
no method named `rev` found for type `std::vec::Vec<i32>` in the current scope
Furthermore:
the method `rev` exists but the following trait bounds were not satisfied: `std::vec::Vec<i32> : std::iter::Iterator`, `[i32] : std::iter::Iterator`
But doesn't a for loop implicitly call IntoIterator? Is &vec or vec.iter() considered idiomatic Rust?
If you're just looping over the Vec, then &vec is idiomatic. This works because &Vec<T> implements IntoIterator, which is what the for loop uses.
However if you want to call Iterator methods such as rev, filter, etc., you need an actual Iterator (since Vec doesn't implement Iterator, only IntoIterator).
So this:
for x in &vec.rev() {
...
}
is equivalent to:
for x in (&vec.rev()).into_iter() {
...
}
i.e. there's no chance to use IntoIterator before trying to call Iterator methods.
This is just basic precedence of the & operator. In the first case, each method is called in turn:
vec.iter().rev()
(vec.iter()).rev() // same
In the second case, the & binds after all the methods:
&vec.rev()
&(vec.rev()) // same
Generally, use &vec when you can, but when you need to use iterator adapter methods, use iter or into_iter.
So if I have an Object and needs to call one method from another within that Object, how do I construct that call?
TestObject = {}
TestObject.__index = TestObject
function TestObject.new()
local self = setmetatable({}, TestObject)
self.value = init
-- a count [integer] of something. Not important what
self.counter = 99
return self
end
function TestObject:getCount()
return self.counter
end
function TestObject:getCountPlus(add_value)
-- HERE HOW SHOULD THIS BE FORMATED??
return self.getCount() + add_value
end
And using this Object would be something like this:
local testObject = TestObject.new()
testObject:getCountPlus(1)
which should result in 100.
The getCount() needs to know what instance it is in. When you write
function TestObject:getCount()
it is same as writing
function TestObject.getCount(self)
(note the colon changed to dot). So calling self.getCount() is like calling getCount with self=nil. Do self:getCount(), which is same as self.getCount(self). This may seem odd: why does interpreter not provide self automatically? It's just the way the language was designed: it only provides self automatically with the : notation.
Say I have the following variable
myClassName = 'myClass';
And I want to call an instance of the myClass constructor function, ie.
myObject = myClass(arg1, arg2, ..., argn);
Let's say I want to call it using myClassName.
myObject = (myClassName)(arg1, arg2, ..., argn); % something like that
How do I do that?
Got it. I found that this:
myFunc = str2func(myClassName);
myClass = myFunc(arg1, arg2, ..., argn);
Does the job.
eval can also be used:
eval([myClassName '(arg1,arg2,arg3)']);
Does the initial variable myClassName actually need to be a string? I would implement this as:
myClassName = #myClass;
myObject = myClassName(arg1, arg2, arg3);
This is pretty similar to using the str2func call from your selfanswer, bit without the string operations which make some people (for example, me) feel wrong.
Is there any dramatic difference between functions and methods in Objective -C?
First, I'm a beginner in Objective-C, but I can say what I know.
Functions are code blocks that are unrelated to an object / class, just inherited from c, and you call them in the way:
// declaration
int fooFunction() {
return 0;
}
// call
int a;
a = fooFunction();
While methods are attached to class / instance (object) and you have to tell the class / object to perform them:
// declaration
- (int)fooMethod {
return 0;
}
// call
int a;
a = [someObjectOfThisClass fooMethod];
It is even simpler; a method is just a C function with the first two argument being the target of the method call and the selector being called, respectively.
I.e. every single method call site can be re-written as an equivalent C function call with absolutely no difference in behavior.
In depth answer here: Why [object doSomething] and not [*object doSomething]? Start with the paragraph that says "Getting back to the C preprocessor roots of the language, you can translate every method call to an equivalent line of C".