Introducing FoundationLite framework as a portable subset of Foundation

foundation

(Amir Abbas Mousavian) #1

While stdlib is great, but it lack some important data types which encapsulate basic data types and I/O. Few topics are suggesting to move some components like Data into stdlib. On the other hand this is not enough for some libraries like SwiftSyntax.

I propose introducing FoundationLite framework which only offer a few basic and handful subset of original Foundation. This framework will be distributed with Swift installation packages - just like stdlib - thus making it available to all platforms. However in Darwin platform, it will be simply a name alias for Foundation.

This list is only a suggestion, community members may think some classes like CharacterSet may fit into lite subset or JSONEncoder does not fit into.

These components will be included into FoundationLite

  • Basic Data Types:

    • NSObject, (NS)Data, (NS)URL, URLComponents, (NS)Date, NSNumber, NSArray, NSDictionary, NSSet, NSOrderedSet, NSString, (NS)Decimal, CGFloat, (NS)IndexPath, UUID, NSValue, NSNull
  • Errors

    • POSIXError, CocoaError
  • Basic Input/Output:

    • (Input/Output)Stream, FileHandle, FileManager (only essential methods)
  • Operating system primitives:

    • Process, Thread, NSLock, Timer, RunLoop, ProcessInfo, Host, Port
  • JSON

    • JSONEncoder, JSONDecoder

These components will be missing in FoundationLite

  • Complementary data types

    • NSAttributedString, CharacterSet, Calendar, Locale, TimeZone, Progress, DateInterval, DateComponents, PersonNameComponents
  • Complementary operating system utilities:

    • Bundle, Operation, Notification, NotificationCenter, UserDefaults
  • Utilities:

    • NSCoder, NSKeyed(Un)Archiver,RegularExpression, NSPredicate, NSExpression, Scanner, NSSortDescriptor
  • Network related types, storages and I/O:

    • URLCredential(Storage), HTTPCookie(Storage), URLCache, URLSession, URLRequest, URLResponse, URLProtocol, URLProtectionSpace, URLAuthenticationChallenge
  • Formatters

  • XMLParser

cc @Joe_Groff @Ben_Cohen @lukasa @compnerd


Update XMLParserDelegate to use KeyValuePairs for attributes dictionary
(Jon Shier) #2

I'm not sure this will work as well as it could or should. While breaking Foundation up seems like the best thing long term for the framework and Swift, it needs to be into multiple modules organized in a dependency tree that can share common types. I'm not familiar enough with all Foundation types to say what that tree would look like, but it would be far more than just a Foundation / Lite / URLSession separation while still under the Foundation umbrella.

I'm also not sure how much effort we should be putting in here, as, to my eyes, Foundation is a temporary compatibility and bootstrapping solution for Swift, not what we want these types and functionality to look like long term. But I guess as long as everything stays under the Foundation umbrella, Swift is free to create it's own replacement types and functionality at some point in the future.


(Amir Abbas Mousavian) #3

I'm not an Apple employee and I don't know what the future direction will be. But lacking a RAII and basic I/O and os primitives is a giant barrier for Swift to become a real multi-platform language. Almost all cross-platform frameworks like Swift-NIO had to reinvent the wheel.

Foundation API became suitable for Swift. Probably Apple will change internal implementation details (Data is a good candidate) but I don't think they will abandon Foundation in a foreseeable future.


(Jon Shier) #4

I agree, and Foundation works (kind of) as a bootstrap for some of those scenarios, and breaking it into pieces may help those users. But its fundamental API design goes back over 20 years and doesn't fit Swift well at all. It's also hugely burdened by being subject to Apple's whims, as any change to API surface must also be implemented by Apple's Foundation team as well as open source Swift contributors. But Swift obviously needs APIs that cover the functionality of Foundation but designed in the open, with common implementation on all platforms, and an API design that starts from Swift's best practices. So far Apple hasn't moved a single angstrom towards that goal, but I find it hard to believe that any engineer there believes Foundation is a good long term solution for Swift. Even if Apple doesn't want to put any effort towards a replacement, just having the core team say that it's a goal would push the community towards building it. But right now, no one uses Foundation because it's a good solution for a problem, they use it's because it's there and Apple hasn't let anything else even get started.


#5

Foundation is great. It's just different from the normal very annoying Linux api most languages support. I count that as a big plus. If I wanted that I wouldn't use a Apple language.


(MTV) #6

FoundationLite would work best if it was pure swift and general purpose, even if its modeled or written similarly to the cocoa apis, which we aren't ready for because of the missing components and OS dependencies. I agree something like I/O should've been address long ago. I hope that gets considered for the first minor version of Swift 5 though its highly unlikely.


(^) #7

Effectively what you’re proposing is to move about a third of Foundation functionality into the standard library, which i might support. I don’t think it’s worth calling it Foundation though, this is a long time coming. I think you drew the line pretty well except I would argue that Date should probably stay in Foundation and XMLParser should be brought into the standard library. Also a lot of these Foundation types are redundant with respect to standard library types and should be dropped entirely: NSDictionary, NSSet, NSString, CGFloat, NSNull, etc. These currently exist for compatibility with Objective C and an external framework is where they belong.


(Amir Abbas Mousavian) #8

I'm not sure if a pure Swifty designed API would differ much from existing one. Indeed many new types like URL or Data are available in Swift overlay of Foundation and their API is kinda new. We have corelibs-swift-foundation almost ready with these components and subsetting them is a not a non-trivial job.

Indeeed some methods like String.hasPrefix() is bridged from NSString. They are not platform-dependent and have no external dependency. They are classes which can be subclassed. Another reason is NSOrderedSet which does not have any counterpart in stdlib and we must retain NSSet then.

It's dependent on libxml2 which is an external dependency, and its usability is faded as it's almost replaced by json.


(Lily Vulcano) #9

This seems to me to not take into account certain relationships between these components. Printing a number requires locale information, for example, and locale information is sourced from defaults. I am positive moving ‘just' the types you mention would require moving several more from the bottom list as well, or at the very least their private implementation.

What is the ultimate goal here? How does this help maintainability or improve the current story in an otherwise tangible way?

I think we’ll be communicating a little about the constraints going forward, but in the meanwhile I would strongly welcome opinions on how to make things ‘more Swifty’ and more findable rather than further fragmenting where APIs live.


(^) #10

you say fragmenting APIs i say breaking up a monolith


(^) #11

it sounds like a reason to transfer some specific string manipulation APIs to the standard library, not the entire NSString type

there’s still a lot of XML out there and we still have to parse it…


(Amir Abbas Mousavian) #12

The ultimate goal is to prevent reinventing wheels like Data (e.g. NIO's ByteBuffer) and make them available for libraries like SwiftSyntax or SPM. These core functionalities are necessary in almost all programs and stdlib lacks them.

You may propose to implement a completely new library, but this is the real fragmentation, not breaking existing monolithic framework into parts. We can't tell developers to learn new API and have multiple solutions for one desired functionality.

I think (but not sure) defaults and Locale implementations are platform-dependent. Out goal is to remove platform-dependency as far possible. I think we can check for availability of these classes in compile-time and print english-format if they are not available.


(Lily Vulcano) #13

This implies that Foundation is undesirable to have in your address space. I want to explore this; why?

(I am personally very much aware of the choices the NIO team had to make, and while I don’t have much to share right now, they have been subject to deep thought to reconcile this situation.)

The goal of Foundation is indeed to enable being that lingua franca, especially given that it already is on Apple platforms. A goal it has is to allow code to be shared between all platforms, not just the ones where the lowest layer is the Swift stdlib.

That is incorrect. Locale and CFPreferences/UserDefaults are platform independent and, with some constraints, work in swift-corelibs-foundation as they are today.

More details about that
  • Locale should work without restrictions, except there is no means currently to modify it while a process is running on Linux the way one can with Language & Region settings on Apple platforms.

  • CFPreferences and UserDefaults work in-process. This means they will work precisely as expected but make no guarantees about the coherence of defaults that have been read or written by multiple processes concurrently. On Apple platforms, we have stricter guarantees.


(Pedro José Pereira Vieito) #14

I think both NIO and SwiftSyntax should be able to import the full Foundation library. If they have any performance problem with it we should optimize Foundation, not try to take it apart.


(Itai Ferber) #15

To add to this a bit:

This is also something I've been wondering deeply about considering the few discussions on the forums in the past few days about this topic. I want to explore this aversion as well — what are the perceived (or real) costs to using Foundation? I haven't been satisfied yet by a real, concrete answer, beyond a perceived feeling of "Foundation is too big"/"Foundation isn't right".

Excuse the generalization, but there's a sense in which we as programmers love to compartmentalize and segment things into neat little boxes, and in many cases, this is beneficial. Too many dependencies, and too much disorganization is indeed not beneficial. But beyond the perceived good feeling we might get from typing import Foundation.JSONEncoder over import Foundation, I want to explore real-life advantages to "breaking down the monolith".

What do folks think would differ if we were able to "split Foundation up"? What will most improve over the current situation?

  • Fewer dependencies? (Both in terms of libraries to import, and in terms of dependencies that Foundation itself has)
  • Improved linking (e.g. smaller linked bundles, less memory usage, etc.)/smaller built apps?
  • More control over API surface and exposition of APIs and methods?

Or is this push to move things into the stdlib (or similar) because of a feeling that Foundation APIs are too different from what the stdlib offers, and so should be altered to fit the style of the stdlib? (Perceived or otherwise.)

No matter what, if there is room for improvement, we should take it.

This is a big one, too. Foundation is meant to be the cross-platform solution that complements the stdlib — if we're building for a given platform, between Foundation on Darwin and swift-corelibs-foundation on our other platforms, you should be able to rely on Foundation in the same way you can rely on the standard library. Why would splitting off some of this functionality in a different library be more cross-platform, more compatible, or better for the ecosystem?


I'm interested in tangible responses here. Getting an understanding of why the status quo does not fit developer needs would really help in advancing us in the right direction in a tangible way.


(Erik Little) #16

What I believe people come to find about Foundation is that it doesn't currently meet the expectations people have for a cross-platform library that is meant to be Swift's main cross platform library. For one, most of it's evolution is governed by internal priorities that must sync with how Foundation on Darwin looks. So people find it limiting that they cannot put Foundation feature requests through SE. I think people would want Swift's Foundation to be decoupled from the legacy NeXTSTEP Foundation that Apple inherited.

A second thing I think people are finding about Foundation is that its Linux support has been pretty slow to develop. URLSession only became somewhat useable after like a year or so of being supported on Linux. Now this point really isn't Apple's fault, it should be us as a community making other OS support decent. And I can't really offer suggestions on how to better community involvement.


(Lily Vulcano) #17

One of the constraints we have is that any code you write on Linux, we want it to work on Darwin and any other platform Foundation compiles on, and vice versa. I know for a fact there’s a lot of value in this; it does mean we need to coordinate between releases we can’t talk much about and the open source library as it is.

My hope is to be able to share more about goals soon, but, for example, Swift 4.2 has had some effort in bringing functionality to unimplemented parts of the library (with a deeper focus: e.g. bridging now works on Linux, removing a big syntax discrepancy between platforms).


URLSession and the Swift Server Work Group
(Amir Abbas Mousavian) #18

I should search this forum to find related, but I remember that NIO can't import because of curl dependency of URLSession

Indeed I think they are platform-dependent because UserDefaults must write a plist or sqlite into disk. Or maybe they are platform-independent but they need external file to store settings.

swift-corelibs-foundation is still incomplete. curl and libxml2 dependency is an obstacle. In addition, some parts are hard to port to new OS like Bundle as they are dependent to directories structure.

That is one of main goal IMO. To make it portable to new operating systems effortlessly.


(Lily Vulcano) #19

Yeah, that’s understood. This is something we need to better isolate; it is on my personal to-do list.

Yup, but that doesn’t make them non-portable. I need to come back to this code and make sure it makes it through, but the goal is to be a good citizen there and make sure those files go in the right location on disk.

For Bundle in particular, we have set up new directory structures designed to be idiomatic on Linux.


(Pedro José Pereira Vieito) #20

Moving Foundation to the full open-source Swift Evolution process and adding a clear roadmap would be great.