Given an array of string, I want to find the first one that can be successfully converted to a real without using exceptions.
The only relevant functions I can see in Phobos are std.conv.to and std.conv.parse, but both of these will throw an exception if they cannot convert the string. I'd like to avoid exceptions because this is not going to be an exceptional circumstance for my use case.
C# provides TryParse for exactly this. Is there anything similar in D?
(of course, I could parse the string myself to determine if it is convertible to real, but it's non-trivial so I'd like to avoid that if possible).
Phobos doesn’t appear to have a way to do this without exceptions, besides std.stream. The problem is that std.stream seems to be deprecated. Here is an example using sscanf with double, though I don’t know how to do it with real:
extern (C) int sscanf(const char* input, const char* format, ...);
auto tryParseDouble(string input) {
import std.string;
import std.typecons;
double result;
if (sscanf(input.toStringz, "%lf".toStringz, &result) == 1) {
return Nullable!double(result);
} else {
return Nullable!double();
}
}
void main() {
import std.algorithm;
import std.range;
import std.stdio;
auto myArray = ["foo", "bar", "3.14", "42"];
auto x = myArray
.map!(tryParseDouble)
.filter!(x => !x.isNull)
.front
.get;
writeln(x);
}
While sscanf() works, it is unsafe. I would open an enhancement request.
Try adapting the Phobos code, returning NaN instead of throwing.
Related
I am pretty new to Swift, and I don't have much exposure to C.
I am trying to write a function in C that will get a Swift string that I can then do something with. The problem is that I'm not 100% sure what the type should be in Swift to make C like what it sees.
So far, I have found several examples on Stack that seem like good starting points, but some examples seem dated for the current version of Swift.
I first started by using this example to get C and Swift talking to one another: Swift call C call Swift? I then took that and tried updating the Swift function to return a string of some kind. I understand that it needs to be a UTF-8 return type, but I'm not sure how to go about sending things properly. I've looked at How to pass a Swift string to a c function?, How to convert String to UnsafePointer<UInt8> and length, and How to convert string to unicode(UTF-8) string in Swift?, but none of them really work for a solution. Or I'm just typing it in incorrectly. So far, the closest I can get to returning something is as follows.
In Swift, my ViewController is:
import UIKit
class ViewController: UIViewController {
#_silgen_name("mySwiftFunc") // give the function a C name
public func mySwiftFunc(number: Int) -> [CChar]
{
print("Hello from Swift: \(number)")
let address: String = "hello there";
let newString = address.cString(using: String.Encoding.utf8)
return newString!
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
blah()
}
}
And in C, the header is like:
#ifndef cfile_h
#define cfile_h
#include <stdio.h>
const char * mySwiftFunc(int);
int blah(void);
#endif /* cfile_h */
And the source is like:
#include "cfile.h"
int blah() {
const char * retVal = mySwiftFunc(42); // call swift function
printf("Hello from C: %s", retVal);
return 0;
}
There is a bridging header file that just has #include "cfile.h". Obviously, there is still a lot of remnants from the first example, and these will be cleaned up later.
What needs to change to make this work? Right now, the console spits out
Hello from Swift: 42
Hello from C: (B\214
The Swift equivalent of const char * is UnsafePointer<CChar>?, so that's the correct return value. Then you have to think about memory management. One options is do allocate memory for the C string in the Swift function, and leave it to the caller to release the memory eventually:
public func mySwiftFunc(number: Int) -> UnsafePointer<CChar>? {
print("Hello from Swift: \(number)")
let address = "hello there"
let newString = strdup(address)
return UnsafePointer(newString)
}
passes a Swift string to strdup() so that a (temporary) C string representation is created automatically. This C string is then duplicated. The calling C function has to release that memory when it is no longer needed:
int blah() {
const char *retVal = mySwiftFunc(42);
printf("Hello from C: %s\n", retVal);
free((char *)retVal);
return 0;
}
⚠️ BUT: Please note that there are more problems in your code:
mySwiftFunc() is an instance method of a class, and therefore has an implicit self argument, which is ignored by the calling C function. That might work by chance, or cause strange failures.
#_silgen_name should not be used outside of the Swift standard library, see this discusssion in the Swift forum.
A slightly better alternative is #_cdecl but even that is not officially supported. #_cdecl can only be used with global functions.
Generally, calling Swift functions directly from C is not officially supported, see this discussion in the Swift forum for the reasons and possible alternatives.
While converting from Swift 2.3 to 3.2 I received below error.
Error : Binary operator cannot be applied to operands of type Int and String
for this if Condition i.e if (error?.code)! == "-112" which is shown in below line.
if (error?.code)! == "-112"
{
print("hello")
}
Error itself says it's different types Int and String.
You can need to typecast one or another in same form and them compare.
if (String(error?.code)!) == "-112"){
print("hello")
}
Swift is a language with a strong type system. You can compare only values of the same type.
Since the left side is Int anyway use an Int value for the right side. Creating a string is unnecessarily expensive. Don’t do that.
The most efficient (and safe) solution is
if error?.code == -112
{
print("hello")
}
You need to type-cast your error code result to a string, like so:
if String(error?.code)!) == "-112" {
print("Hello")
}
Essentially, you are taking the error?.code, "casting" it as a string by placing it in a string "container mould" and unwrapping the value (retrieving the casted result).
In addition, if you are working with an API response, you have to account for all other error codes in the else/if statement to make sure all responses are handled properly (just in case you are).
I am trying to extract the extension of a file from a given String path.
The following piece of code works, but I was wondering if there is a cleaner and more idiomatic Rust way to achieve this:
use std::path::Path;
fn main() {
fn get_extension_from_filename(filename: String) -> String {
//Change it to a canonical file path.
let path = Path::new(&filename).canonicalize().expect(
"Expecting an existing filename",
);
let filepath = path.to_str();
let name = filepath.unwrap().split('/');
let names: Vec<&str> = name.collect();
let extension = names.last().expect("File extension can not be read.");
let extens: Vec<&str> = extension.split(".").collect();
extens[1..(extens.len())].join(".").to_string()
}
assert_eq!(get_extension_from_filename("abc.tar.gz".to_string()) ,"tar.gz" );
assert_eq!(get_extension_from_filename("abc..gz".to_string()) ,".gz" );
assert_eq!(get_extension_from_filename("abc.gz".to_string()) , "gz");
}
In idiomatic Rust the return type of a function that can fail should be an Option or a Result. In general, functions should also accept slices instead of Strings and only create a new String where necessary. This reduces excessive copying and heap allocations.
You can use the provided extension() method and then convert the resulting OsStr to a &str:
use std::path::Path;
use std::ffi::OsStr;
fn get_extension_from_filename(filename: &str) -> Option<&str> {
Path::new(filename)
.extension()
.and_then(OsStr::to_str)
}
assert_eq!(get_extension_from_filename("abc.gz"), Some("gz"));
Using and_then is convenient here because it means you don't have to unwrap the Option<&OsStr> returned by extension() and deal with the possibility of it being None before calling to_str. I also could have used a lambda |s| s.to_str() instead of OsStr::to_str - it might be a matter of preference or opinion as to which is more idiomatic.
Notice that both the argument &str and the return value are references to the original string slice created for the assertion. The returned slice cannot outlive the original slice that it is referencing, so you may need to create an owned String from this result if you need it to last longer.
What's more idiomatic than using Rust's builtin method for it?
Path::new(&filename).extension()
I'm sure there is a simple answer to this but I'm banging my head here.
In my Swift 2 code (Xcode 7.2.1) I am using CFByteOrderGetCurrent() to get the byte ordering of the local machine.
I can't figure out how to evaluate the result of the function - the 'if' statement in the following fails compilation with
"type of expression is ambiguous without more context":
import Foundation
let byteOrder = CFByteOrderGetCurrent()
if byteOrder == .CFByteOrderLittleEndian { // compilation fails here
/* do something */
}
From the CF documentation I was to expecting the result of the function to be an enum, but when I try it in a playground it seems to be an Int ...
CFByteOrder is a typealias of CFIndex.
It is an enum, which consists of the following values:
CFByteOrderUnknown,
CFByteOrderLittleEndian,
CFByteOrderBigEndian
Thus, CFByteOrderLittleEndian corresponds to 1.
In order to do the comparison, one may need to do the following:
if byteOrder == CFByteOrder(1)
{
print(byteOrder)
}
1 here corresponds to CFByteOrderLittleEndian.
i am using a little bit different trick ...
if 1.littleEndian == 1 {
print("little endian")
} else {
print("big endian")
}
generally
let isLittleEndian = 1.littleEndian == 1
is true on little endian system, false on big endian system. the advantage is, that it works on all platforms
OK I finally cracked how to make the comparison using symbolic constants.
If you convert the result of CFByteOrderGetCurrent() into a UInt32 then you can compare it to the raw value of the constants in the enumeration:
import Foundation
let hostByteOrder = UInt32(CFByteOrderGetCurrent())
if hostByteOrder == CFByteOrderLittleEndian.rawValue {
print("little")
}
I've recently started trying to write some toy programs in rust, and I guess I wanted to take a stab at a parser combinator.
My naive attempt was this:
enum ParseResult<T> {
Ok(T),
Error (String),
}
struct Parser<'a, I,O>{
Parse: |I|:'a ->ParseResult<O>,
}
impl<'a, I,O,J> Parser<'a, I, O>{
fn Compose<I,O,K>(self, RHS : Parser<O,K> )->Parser<I,K>{
Parser
{
Parse : |x:I|
{
let intermediate = self.Parse;
match intermediate(x){ //mismatched types: expected `I` but found `I` (expected type parameter but found type parameter)
Ok(result) =>
{
let final = RHS.Parse;
final(result) mismatched types: expected `O` but found `0` (expected type parameter but found type parameter)
}
Error(result) => Error(result)
}
}
}
}
}
I'm pretty sure the Errors indicate something more fundamentally wrong with my approach but I'm not quite sure what.
Indeed, there is a couple of errors in your program.
Currently closures are stack-"boxed", so you can't return them from functions, and that's exactly what happening in your example - you're storing a closure in Parser struct.
Another error is incorrect usage of generic parameters. Even without closures your method wouldn't work: I and O parameters on Compose method are different from those on impl clause, even if they share the same name.
BTW, you don't need to move a closure into intermediate variable. To call closures stored in fields you need to do this:
let intermediate = (self.Parse)(x);
That said, several days ago unboxed closures finally landed. With them it is possible to do what you want, though it is somewhat cumbersome at the moment.
#![feature(unboxed_closures)]
struct Parser<I, O> {
parse: Box<FnMut<(I,), Result<O, String>>>
}
impl<I, O> Parser<I, O> {
fn compose<K>(mut self, mut rhs: Parser<O, K>) -> Parser<I, K> {
Parser {
parse: box |&mut: x: I| {
match self.parse.call_mut((x,)) {
Ok(r) => rhs.parse.call_mut((r,)),
Err(e) => Err(e)
}
}
}
}
}
This should work but right now it doesn't, and it looks like a bug to me:
<anon>:11:23: 11:33 error: cannot borrow data mutably in an aliasable location
<anon>:11 match self.parse.call_mut((x,)) {
^~~~~~~~~~
<anon>:12:35: 12:44 error: cannot borrow data mutably in an aliasable location
<anon>:12 Ok(result) => rhs.parse.call_mut((result,)),
^~~~~~~~~
When I rewritten this example with manually expanded unboxed closure it worked, so there's definitely some compiler problem here. Unboxed closures are very new, so such things are not unexpected. I've submitted an issue on this.