Variadic opIndex Override - operator-overloading

Following my previous question, I'm now having trouble overriding opIndex with variadic parameters. I've tried multiple methods (even hack-ish ones) but to no avail.
The code I'm using to generate the identifier string
static string array_decl(D...)(string identifier, D dimensions)
{
static if(dimensions.length == 0)
{
return identifier;
}
else
{
return array_decl(identifier ~ "[" ~ to!(string)(dimensions[0]) ~ "]", dimensions[1..$]);
}
}
What my opIndex override looks like:
T opIndex(D...)(D indices)
{
mixin("return " ~ array_decl("Data", indices) ~ ";");
}
Fails with:
./inheritance.d(81): Error: tuple D is used as a type
./inheritance.d(89): Error: template instance inheritance.array_ident!(int, int, int).array_ident.array_ident!(_param_2, _param_3) error instantiating
./inheritance.d(112): instantiated from here: array_ident!(int, int, int)
./inheritance.d(174): instantiated from here: opIndex!(int, int, int)
./inheritance.d(112): Error: CTFE failed because of previous errors in array_ident
./inheritance.d(112): Error: argument to mixin must be a string, not ("return " ~ array_ident("Data", _param_0, _param_1, _param_2) ~ ";") of type string
The question is how (or is it possible) to implement the opIndex operator for this situation.
I think mixins are the way to go since I only have to generate a string with the format of:
type[index0][index1]...[indexN] Data
for the opIndex overload.

Apparently this is not possible as the tuple passed to opIndex is inaccessible at compile-time. A few solutions I came up with (by Adam D. Ruppe's suggestions):
1. Hard-coding Array Access
Using compile-time conditions to index the array, a bit ugly and the amount of dimensions that can be accessed depends on the amount of conditions implemented.
T opIndex(D...)(D indices)
{
static if(indices.length == 1)
{
return Data[indices[0]];
}
static if(indices.length == 2)
{
return Data[indices[0]][indices[1]];
}
static if(indices.length == 3)
{
return Data[indices[0]][indices[1]][indices[2]];
}
static if(indices.length == 4)
{
return Data[indices[0]][indices[1]][indices[2]][indices[3]];
}
}
2. Pointer(s)
The only other method was to cast the array to a pointer then use offsets. The offset is computed and is then used to index the pointer.
To be able to access the template parameters at run-time:
struct Vector_MultiDim(T, D...)
{
enum dimensions = [D];
static const size_t DimCount = D.length;
... Other members here
}
Function to compute offset (the size of each dimension must be known at run-time):
size_t GetIndex(size_t[] indices)
{
size_t index;
for(size_t i = 0; i < DimCount; i++)
{
size_t factor = 1;
for(size_t j = i + 1; j < DimCount; j++)
{
factor *= dimensions[j];
}
index += indices[i] * factor;
}
return index;
}
opIndex Override:
T opIndex(D...)(D indices)
{
T* arr = cast(T*)Data;
return arr[GetIndex([indices])];
}

Related

How to return a variable in a function in kotlin

I created a function that recieves input and compare it to a list, when find a match it return the match, in this case this match is the attribute of a class that i created.
I understand that the problem is with the return statement, so in the beginning of the function I declare the return as "Any", further more than that I'm kinda lost.
The error is this: A 'return' expression required in a function with a block body ('{...}')
class Class1(var self: String)
var test_class = Class1("")
fun giver(){
test_class.self = "Anything"
}
class Funciones(){
fun match_finder(texto: String): Any{
var lista = listOf<String>(test_class.self)
var lista_de_listas = listOf<String>("test_class.self")
var count = -1
for (i in lista_de_listas){
count = count + 1
if (texto == i){
lista_de_listas = lista
var variable = lista_de_listas[count]
return variable
}
}
}
}
fun main(){
giver()
var x = "test_class.self"
var funcion = Funciones()
var y = funcion.match_finder(x)
println(y)
}
To explain you what the problem is, let's consider the following code:
class MyClass {
fun doSomething(): String {
val numbers = listOf(1, 2, 3)
for (number in numbers) {
if (number % 2 == 0) {
return "There is at least one even number in the list"
}
}
}
}
If you try compiling it you'll get the same error message as in your question: A 'return' expression required in a function with a block body ('{...}'). Why is that?
Well, we defined a function doSomething returning a String (it could be any other type) but we're returning a result only if the list of numbers contains at least one even number. What should it return if there's no even number? The compiler doesn't know that (how could it know?), so it prompts us that message. We can fix the code by returning a value or by throwing an exception:
class MyClass {
fun doSomething(): String {
val numbers = listOf(1, 2, 3)
for (number in numbers) {
if (number % 2 == 0) {
return "There is at least one even number in the list"
}
}
// return something if the list doesn't contain any even number
return "There is no even number in the list"
}
}
The same logic applies to your original code: what should the function return if there is no i such that texto == i?
Please also note that the solution you proposed may be syntactically correct - meaning it compiles correctly - but will probably do something unexpected. The for loop is useless since the if/else statement will always cause the function to return during the first iteration, so the value "There is no match" could be returned even if a match actually exists later in the list.
I searched online, if someone has the same problem, the correct code is as follows:
class Funciones(){
fun match_finder(texto: String): Any{
var lista = listOf<String>(test_class.self)
var lista_de_listas = listOf<String>("test_class.self")
var count = -1
var variable = " "
for (i in lista_de_listas){
count = count + 1
if (texto == i){
lista_de_listas = lista
var variable = lista_de_listas[count]
return variable
} else {
return "There is no match"
}
}
return variable
}
}

swift 3 variable used before begin initialized

I have an issue with my n variable. I cannot use n in for loop. Why? n was initialized before for loop. Please, help.
import Foundation
var n: Int
var t: Int
while(true){
var tt = readLine()
t = Int(tt!)!
if (t==0){
break
}
else if ( t < 0){
n = t*(-1)
}
else if(t > 0){
n = t
}
var arr : [[String]] = []
for i in 0..<n*2{
for y in 0..<n*2{
arr[i][y] = "."
}
}
}
A variable may be declared and not immediately initialized, as long as initialization is guaranteed before first use
The error is more subtle than at first glance. You may actually declare a property without initializing it, as long as all program flows leading to its first use ascertain initialization of it.
The issue is with the if, else if and else if block:
var n: Int // declaration
// ...
if (t == 0) {
break
}
else if (t < 0) {
n = t*(-1)
}
else if (t > 0){
n = t
}
// first use
for i in 0..<n*2 { /* ... */ }
Swift cannot not infer that this block is in fact exhaustive, and believes that there is a possibility that none of the above if statements holds, which, in the eyes of the compiler, would lead to the following program state:
program flow has not been broken (break)
and n has not been instantiated
As humans, however, we know that the if - else if - else if block above is indeed exhaustive, and can help the compiler out by simply changing the last if else statement to a simple else statement.
if (t == 0) {
break
}
else if (t < 0) {
n = t*(-1)
}
// if none of the above, t > 0
else {
n = t
}
On another note, the nested array access of non-existing array elements, arr[i][y] = "." will lead to a runtime exception, but this is another issue. In its current form, it looks as if the intent with the nested loops could be replaced with a nested array instantiation:
var arr = [[String]](repeating: [String](repeating: ".", count: 2*n), count: 2*n)
or,
var arr = (0..<2*n).map { _ in [String](repeating: ".", count: 2*n) }
The variable n is only declared, not initialized.
To initialize the variables:
var n: Int = 0
var t: Int = 0

Swift Type 'string.index' has no subscript members

I'm currently converting C++ code to Swift and I've gotten stuck on one part. The parameter passed into the function is a string and the area where I'm stuck is when attempting to set a variable based on the second to last character of a string to check for a certain character.
The error shows up on this line:
line[i-1]
I've tried casting this value to an Int but this didn't work:
Int(line[i - 1])
I've also tried to see if the string's startIndex function which takes a Int would work but it didn't:
line.startIndex[i - 1]
Here is the full function:
func scanStringForSpecificCharacters(line: String){
var maxOpen: Int = 0;
var minOpen: Int = 0;
minOpen = 0;
maxOpen = 0;
var i = 0
while i < line.characters.count {
for character in line.characters {
//var c: Character = line[i];
if character == "(" {
maxOpen += 1;
if i == 0 || line[i - 1] != ":" {
minOpen += 1;
}
}
else if character == ")"{
minOpen = max(0,minOpen-1);
if i == 0 || line[i-1] != ":"{
maxOpen -= 1;
}
if maxOpen < 0{
break;
}
}
}
if maxOpen >= 0 && minOpen == 0{
print("YES")
}else{
print("NO")
}
}
}
Strings in Swift aren't indexed collections and instead you can access one of four different views: characters, UTF8, UTF16, or unicodescalars.
This is because Swift supports unicode, where an individual characters may actually be composed of multiple unicode scalars.
Here's a post that really helped me wrap my head around this: https://oleb.net/blog/2016/08/swift-3-strings/
Anyway, to answer you question you'll need to create an index using index(after:), index(before:), or index(_, offsetBy:).
In your case you'd want to do something like this:
line.index(line.endIndex, offsetBy: -2) // second to last character
Also, you'll probably find it easier to iterate directly using a String.Index type rather than Int:
let line = "hello"
var i = line.startIndex
while i < line.endIndex {
print(line[i])
i = line.index(after: i)
}
// prints ->
// h
// e
// l
// l
// o
Working with Strings in Swift was changed several times during it's evolution and it doesn't look like C++ at all. You cannot subscript string to obtain individual characters, you should use index class for that. I recommend you read this article:
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/StringsAndCharacters.html
As already pointed out in the other answers, the compiler error
is caused by the problem that you cannot index a Swift String with
integers.
Another problem in your code is that you have a nested loop which is
probably not intended.
Actually I would try to avoid string indexing at all and only
enumerate the characters, if possible. In your case, you can
easily keep track of the preceding character in a separate variable:
var lastChar: Character = " " // Anything except ":"
for char in line.characters {
if char == "(" {
maxOpen += 1;
if lastChar != ":" {
minOpen += 1;
}
}
// ...
lastChar = char
}
Or, since you only need to know if the preceding character is
a colon:
var lastIsColon = false
for char in string.characters {
if char == "(" {
maxOpen += 1;
if !lastIsColon {
minOpen += 1;
}
}
// ...
lastIsColon = char == ":"
}
Another possible approach is to iterate over the string and a shifted
view of the string in parallel:
for (lastChar, char) in zip([" ".characters, line.characters].joined(), line.characters) {
// ...
}
As others have already explained, trying to index into Swift strings is a pain.
As a minimal change to your code, I would recommend that you just create an array of the characters in your line up front:
let linechars = Array(line.characters)
And then anywhere you need to index into the line, use linechars:
This:
if i == 0 || line[i-1] != ":" {
becomes:
if i == 0 || linechars[i-1] != ":" {

Binary operator < cannot be applied to Clong in Swift

I am trying to implement the following code in swift. But my i variable refuse to talk to my MAXADDRS. It says binary operator < cannot be applied to Clong in Swift. If I use CInt the problem goes away, but then I get an error on the variable i when assiginin theAddr = ip_addrs[i]
InitAddresses();
GetIPAddresses();
GetHWAddresses();
var i = CLong()
var deviceIP = NSString()
for (i=0; i < MAXADDRS; ++i)
{
var localHost = 0x7F000001; // 127.0.0.1
var theAddr = CLong()
theAddr = ip_addrs[i]
if (theAddr == 0) {return}
if (theAddr == localHost){continue}
NSLog("Name: %s MAC: %s IP: %s\n", if_names[i], hw_addrs[i], ip_names[i]);
//decided what adapter you want details for
if (strncmp(if_names[i], "en", 2) == 0)
{
NSLog("Adapter en has a IP of %s", ip_names[i]);
}
}
// Do any additional setup after loading the view, typically from a nib.
}
The MAXADDRS it intends to compare relates to the following OBC header
Source files here
http://www.chrisandtennille.com/code/IPAddress.h
http://www.chrisandtennille.com/code/IPAddress.c
My bridging header
#include "IPAddress.h"
#include "IPAddress.c"
#define MAXADDRS 32
is imported to Swift as
public var MAXADDRS: Int32 { get }
On the other hand, CLong is an alias for Int ("The C 'long' type.")
Therefore you need to convert all values to a common type. Since
array subscripting requires an Int index, converting MAXADDRS
to Int might be the easiest solution:
var i = 0 // Int
for (i=0; i < Int(MAXADDRS); ++i) {
}
or more simply:
for i in 0 ..< Int(MAXADDRS) {
}

What is the equivalent Scala code for this Imperative coding style?

Find below the imperative style code:
private boolean placePieceOnBoard(Results results,
ChessLayout chessLayout,
List<ChessPiece> piecesToPlace,
int pieceIndex,
int startOffset) {
if(pieceIndex == piecesToPlace.size()) {
results.addLayout(chessLayout);
return true;
}
else {
ChessPiece chessPiece = piecesToPlace.get(pieceIndex);
int offset = startOffset;
while(offset < chessLayout.getBoardLength()) {
int placedOffset = chessLayout.placePieceInNextAvailablePosition(chessPiece, offset);
if( placedOffset == ChessLayout.NULL_OFFSET )
break;
else {
logger.debug("piece {} ({}) moved", pieceIndex, chessPiece);
placePieceOnBoard(results, chessLayout.clone(), piecesToPlace, pieceIndex + 1, placedOffset + 1);
chessLayout.removeChessPiece(chessPiece);
offset = placedOffset + 1;
}
}
return false;
}
}
Here I am interested in knowing how to convert changes made to offset within the loop in a functional way, how to do early break from the loop etc.
This is a nice demonstration of one of Scala's great strengths - gradual, easy migration from imperative Java code to functional code.
To convert to Scala, you don't need to go 100% functional straight away. You can easily convert what you have to Scala as follows:
def placePieceOnBoard(results: Results,
chessLayout: ChessLayout,
piecesToPlace: List[ChessPiece],
pieceIndex: Int,
startOffset: Int) {
if (pieceIndex == piecesToPlace.size()) {
results.addLayout(chessLayout)
true
}
else {
val chessPiece = piecesToPlace.get(pieceIndex)
var offset = startOffset
while(offset < chessLayout.getBoardLength) {
val placedOffset = chessLayout.placePieceInNextAvailablePosition(chessPiece, offset)
if( placedOffset == ChessLayout.NULL_OFFSET )
break
else {
logger.debug("piece {} ({}) moved", pieceIndex, chessPiece)
placePieceOnBoard(results, chessLayout.clone(), piecesToPlace, pieceIndex + 1, placedOffset + 1)
chessLayout.removeChessPiece(chessPiece)
offset = placedOffset + 1
}
}
false
}
}
Note we already have some small improvements in verbosity: no more ;s, no redundant type signatures, mutable variables converted to constants where possible, eliminated return statements and function brackets. Note I changed the argument type of piecesToPlace to a scala list, you'll need to use the scala-java converters at the call site to make this compile.
Next, we can start making this more functional... however, this function probably isn't the place you should start, as you are calling state-mutating functions in several places. For example, you could start with ChessLayout:
chessLayout.removeChessPiece(chessPiece)
val placedOffset = chessLayout.placePieceInNextAvailablePosition(chessPiece, offset)
These methods mutate ChessLayout, which is not functional style. You could modify removeChessPiece to return a new ChessLayout with the piece removed, and placePieceInNextAvailablePosition could return a tuple of (ChessLayout, Int). Once you have stopped any functions called from placePieceOnBoard from mutating state, you can then convert it to functional style.