The questions are embedded in comments as well as here:
Linked List implementation:
public class Node<T>
{
public var data: T
public var next: Node<T>?
//1.
//How can I define a default datatype for T?
//In C++ I would let T ctor do it: "data: T = T()" gives
//error: 'T' cannot be constructed because it has no accessible initializers
public init(data: T, next: Node<T>?)
{
self.data = data
self.next = next
}
}
func print<T>(head: Node<T>)
{
var tmp = head //2. Is this a copy of a pointer or an object?
print(tmp.data)
while(tmp.next != nil) //3. Any Swiftier way to do it?
{
tmp = tmp.next!
print(tmp.data)
}
}
func insert<T>(head: Node<T>, _ value: T)
{
var tmp = head
while tmp.next != nil
{
tmp = tmp.next!
}
tmp.next = Node<T>(data: value, next: nil)
}
var head = Node<Int>(data: 1, next: nil)
insert(head, 2)
insert(head, 4)
insert(head, 8)
insert(head, 16)
print(head)
Also, any other comments? I'm very new to Swift
1.
Generics is all about code safety without knowing the type on compile time. That means it would make no sense to initialise a generic type to something. However by declaring a protocol like
protocol Initializable {
init()
}
, extending the types you want to use by doing
extension Int : Initializable {}
(maybe implement the init()
method yourself) and declaring your node like
public class Node<T: Initializable>
you can use T()
in your initialiser to create the initial value. Because now the compiler knows that this type does indeed have such an initialiser because it conforms to that protocol.
2.
Classes are always passed as a reference whereas structs are always copied
To be able to change an input value of a function it has to be declared as inout
like
func insert<T>(inout head: Node<T>, _ value: T)
Then you also need to call the function like insert(&head, 2)
3.
You could write the loop like
while let next = tmp.next {
tmp = next
print(tmp.data)
}
4.
Swift is a beautiful language, and I strongly suggest you to use more Swiftier code in general.
The way you wrote those 2 methods is as if in C. You can put functions in classes and this is the optimal way to do it and it's also much simpler.
Not very important I admit, but this style of curly brackets is outdated
You don't need to declare a function as public if you don't really need it. And you only need it when writing a framework or something along those lines. The default behaviour (no access control modifier) is to have access to all your Swift files in the whole project.
This Initializable
protocol I made here isn't really Swifty either
Brackets around while (boolean)
are not needed and aren't Swifty
Named parameters are there for a reason: To make code more readable. Only remove them when you're absolutely sure that it's annoying and it's clear what the parameter represents.
I didn't want to do this originally but I redid your code in a much more Swifty way and I hope I can help you with that:
protocol DefaultValuable {
static func defaultValue() -> Self
}
extension Int : DefaultValuable {
static func defaultValue() -> Int {
return 1
}
}
class Node<T: DefaultValuable> {
var data: T
var next: Node<T>?
init(data: T = T.defaultValue(), next: Node<T>? = nil) {
self.data = data
self.next = next
}
func printNode() {
var tmp = self
print(tmp.data)
while let next = tmp.next {
tmp = next
print(tmp.data)
}
}
func insert(value: T) {
var tmp = self
while let next = tmp.next {
tmp = next
}
tmp.next = Node<T>(data: value)
}
}
let head = Node<Int>()
head.insert(2)
head.insert(4)
head.insert(8)
head.insert(16)
head.printNode()
(Sorry for the kinda rant)
You can't do this, in Swift. You could make data
an optional, or overload init
for specific types, but self.data = T()
or similar isn't possible.
Variables for objects made from classes are always reference type in Swift, so basically pointers under the hood.
Your print
function could be better written:
func print<T>(head: Node<T>)
{
var tmp: Node<T>? = head
while let currentNode = tmp
{
print(currentNode.data)
tmp = tmp?.next
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With